How to check the extension of a filename in a bash script?
Question
I am writing a nightly build script in bash.
Everything is fine and dandy except for one little snag:
#!/bin/bash
for file in "$PATH_TO_SOMEWHERE"; do
if [ -d $file ]
then
# do something directory-ish
else
if [ "$file" == "*.txt" ] # this is the snag
then
# do something txt-ish
fi
fi
done;
My problem is determining the file extension and then acting accordingly. I know the issue is in the if-statement, testing for a txt file.
How can I determine if a file has a .txt suffix?
Solution
I think you want to say "Are the last four characters of $file equal to .txt
?" If so, you can use the following:
if [ ${file: -4} == ".txt" ]
Note that the space between file:
and -4
is required, as the ':-' modifier means something different.
OTHER TIPS
Make
if [ "$file" == "*.txt" ]
like this:
if [[ $file == *.txt ]]
That is, double brackets and no quotes.
The right side of ==
is a shell pattern.
If you need a regular expression, use =~
then.
You just can't be sure on a Unix system, that a .txt file truly is a text file. Your best bet is to use "file". Maybe try using:
file -ib "$file"
Then you can use a list of MIME types to match against or parse the first part of the MIME where you get stuff like "text", "application", etc.
You can use the "file" command if you actually want to find out information about the file rather than rely on the extensions.
If you feel comfortable with using the extension you can use grep to see if it matches.
You could also do:
if [ "${FILE##*.}" = "txt" ]; then
# operation for txt files here
fi
Similar to 'file', use the slightly simpler 'mimetype -b' which will work no matter the file extension.
if [ $(mimetype -b "$MyFile") == "text/plain" ]
then
echo "this is a text file"
fi
Edit: you may need to install libfile-mimeinfo-perl on your system if mimetype is not available
I wrote a bash script that looks at the type of a file then copies it to a location, I use it to look through the videos I've watched online from my firefox cache:
#!/bin/bash
# flvcache script
CACHE=~/.mozilla/firefox/xxxxxxxx.default/Cache
OUTPUTDIR=~/Videos/flvs
MINFILESIZE=2M
for f in `find $CACHE -size +$MINFILESIZE`
do
a=$(file $f | cut -f2 -d ' ')
o=$(basename $f)
if [ "$a" = "Macromedia" ]
then
cp "$f" "$OUTPUTDIR/$o"
fi
done
nautilus "$OUTPUTDIR"&
It uses similar ideas to those presented here, hope this is helpful to someone.
I guess that '$PATH_TO_SOMEWHERE'
is something like '<directory>/*'
.
In this case, I would change the code to:
find <directory> -maxdepth 1 -type d -exec ... \;
find <directory> -maxdepth 1 -type f -name "*.txt" -exec ... \;
If you want to do something more complicated with the directory and text file names, you could:
find <directory> -maxdepth 1 -type d | while read dir; do echo $dir; ...; done
find <directory> -maxdepth 1 -type f -name "*.txt" | while read txtfile; do echo $txtfile; ...; done
If you have spaces in your file names, you could:
find <directory> -maxdepth 1 -type d | xargs ...
find <directory> -maxdepth 1 -type f -name "*.txt" | xargs ...
The correct answer on how to take the extension available in a filename in linux is :
${strFileName##*\\.}
Example of printing all file extensions in a directory
for fname in $(find . -maxdepth 1 -type f) # only regular file in the current dir
do echo ${fname##*\.} #print extensions
done
My take on it with cut
>cut -d'.' -f2<<<"hi_mom.txt"
txt
My take on it with awk would be something like the following.
>MY_DATA_FILE="my_file.sql"
>FILE_EXT=$(awk -F'.' '{print $NF}' <<< $MY_DATA_FILE)
>if [ "sql" = "$FILE_EXT" ]
>then
> echo "file is sql"
>fi
>awk -F'.' '{print $NF}' <<eof
>hi_mom.txt
>my_file.jpg
>eof