Bash script: check if a file is a text file
From the fact that it says
file $attachment
rather thanfile "$attachment"
, I guess your script cannot handle filenames that contain spaces. But, be advised that filenames can contain spaces, and well-written scripts can handle them. Note, then:$ file "foo bar" foo bar: ASCII text $ file "foo bar" | cut -d' ' -f2 bar:
One popular and highly recommended approach is to null-terminate the filenames:
$ file -0 "foo bar" | cut -d $'\0' -f2 : ASCII text
The
file
command makes educated guesses about what type of file a file is. Guesses, naturally, are sometime wrong. For example,file
will sometimes look at an ordinary text file and guess that it is a shell script, C program, or something else. So you don't want to check whether the output fromfile
isASCII text
, you want to see whether it says that the file is a text file. If you look at the man page forfile
, you will see that it more-or-less promises to include the wordtext
in its output if the file is a text file, but this might be in a context likeshell commands text
. So, it may be better to check whether the output fromfile
contains the wordtext
:isFile=$(file -0 "$attachment" | cut -d $'\0' -f2) case "$isFile" in (*text*) echo "$attachment is a text file" ;; (*) echo "$attachment is not a text file, please use a different file" ;; esac
The problem occurs in cut -d\ -f2
. Change it to cut -d\ -f2
.
To cut
, the arguments look like this:
# bash: args(){ for i; do printf '%q \\\n' "$i"; done; }
# args cut -d\ -f2
cut \
-d\ -f2 \
And here is the problem. \
escaped the space to a space literal instead of a delimiter between arguments in your shell, and you didn't add an extra space so the whole -d\ -f2
part appears as one argument. You should add one extra space so -d\
and -f2
appear as two arguments.
To avoid confusion, many people use quotes like -d' '
instead.
P.S.: Instead of using file and making everything ASCII, I'd rather use
if file "$attachment2" | grep -q text$; then
# is text
else
# file doesn't think it's text
fi
case $(file -b --mime-type - < "$attachment") in
(text/*)
printf '%s\n' "$attachment is probably text according to file"
case $(file -b --mime-encoding - < "$attachment") in
(us-ascii) echo "and probably in ASCII encoding"
esac
esac