1

I am working on a bash script which execute a command depending on the file type. I want to use the the "file" option and not the file extension to determine the type, but I am bloody new to this scripting stuff, so if someone can help me I would be very thankful! - Thanks!

Here the script I want to include the function:

 #!/bin/bash

 export PrintQueue="/root/xxx";

 IFS=$'\n'

 for PrintFile in $(/bin/ls -1 ${PrintQueue}) do

     lpr -r ${PrintQueue}/${PrintFile};

 done

The point is, all files which are PDFs should be printed with the lpr command, all others with ooffice -p

John
  • 11
  • 1
  • In addition to the good advice presented below: you don't need to use `export` here; the `do` keyword needs to be preceded by a semi-colon or appear on a new line. – glenn jackman Jun 26 '11 at 23:57

3 Answers3

1

You are going through a lot of extra work. Here's the idiomatic code, I'll let the man page provide the explanation of the pieces:

#!/bin/sh

for path in /root/xxx/* ; do
    case `file --brief $path` in
      PDF*) cmd="lpr -r" ;;
      *) cmd="ooffice -p" ;;
    esac
    eval $cmd \"$path\"
done

Some notable points:

  • using sh instead of bash increases portability and narrows the choices of how to do things
  • don't use ls when a glob pattern will do the same job with less hassle
  • the case statement has surprising power
msw
  • 42,753
  • 9
  • 87
  • 112
  • PDF files may not always have .pdf/.PDF extension. Your solution may not cover those cases. I agree with using globing whenever possible. – gsbabil Jun 26 '11 at 11:56
  • your code may not also cover file-names with spaces in them. You should consider changes IFS. – gsbabil Jun 26 '11 at 12:06
  • Just don't call `eval`! And if you're going to assume that `file` has a `--brief` option, scratch that and use `file -i`, to get a nicely parseable MIME type as output. – Gilles 'SO- stop being evil' Jun 26 '11 at 12:20
0
#!/bin/bash

PRINTQ="/root/docs"

OLDIFS=$IFS
IFS=$(echo -en "\n\b")

for file in $(ls -1 $PRINTQ)
do
        type=$(file --brief $file | awk '{print $1}')
        if [ $type == "PDF" ]
        then
                echo "[*] printing $file with LPR"
                lpr "$file"
        else
                echo "[*] printing $file with OPEN-OFFICE"
                ooffice -p "$file"
        fi  
done

IFS=$OLDIFS
gsbabil
  • 7,505
  • 3
  • 26
  • 28
  • Changing `IFS` doesn't help much. The root of the problem is parsing the output of `ls`. [Don't do that.](http://mywiki.wooledge.org/ParsingLs) Your parsing of `file`'s output isn't robust: different versions of `file` might put `PDF` at a different place on the line. If you're going to make assumptions on the `file` implementation, use `file -i` to make it output a MIME type. – Gilles 'SO- stop being evil' Jun 26 '11 at 12:23
  • @Gilles: thanks for the comments. May be `file --brief` as @msw used above is a better approach. It'll always produce PDF at the beginning of the line. – gsbabil Jun 28 '11 at 09:49
0

First, two general shell programming issues:

  • Do not parse the output of ls. It's unreliable and completely useless. Use wildcards, they're easy and robust.
  • Always put double quotes around variable substitutions, e.g. "$PrintQueue/$PrintFile", not $PrintQueue/$PrintFile. If you leave the double quotes out, the shell performs wildcard expansion and word splitting on the value of the variable. Unless you know that's what you want, use double quotes. The same goes for command substitutions $(command).

Historically, implementations of file have had different output formats, intended for humans rather than parsing. Most modern implementations have an option to output a MIME type, which is easily parseable.

#!/bin/bash
print_queue="/root/xxx"
for file_to_print in "$print_queue"/*; do
  case "$(file -i "$file_to_print")" in
    application/pdf\;*|application/postscript\;*)
      lpr -r "$file_to_print";;
    application/vnd.oasis.opendocument.*)
      ooffice -p "$file_to_print" &&
      rm "$file_to_print";;
    # and so on
    *) echo 1>&2 "Warning: $file_to_print has an unrecognized format and was not printed";;
  esac
done
Gilles 'SO- stop being evil'
  • 104,111
  • 38
  • 209
  • 254