Filter Hidden Files with Bash (for Batch Image Resize Script)
I'm writing a script to batch resize images. Originally I was applying an operation for file in $(ls $1)
, but I would like to be able to use globbing, so I'm looking at something more like for file in $(echo $1)
. The problem is that dotglob may or may not be enabled, so echo *
could return hidden files (notably, .DS_Store), which cause convert
to throw an error and stop the script. I would like the default behavior of the command to be that if I cd
into a directory full of images and execute resize * 400x400 jpg
, all of the images will be resized excluding hidden files, regardless of whether dotglob is enabled.
So, in pseudo code, I'm looking for:
for file in $(echo $1 | [filter-hidden-files])
Here is my script with the older behavior. Will update with new behavior when I find a solution:
# !/bin/bash
# resize [folder] [sizeXxsizeY] [outputformat]
# if [outputformat] is omitted, the input file format is assumed
for file in $(ls $1)
do
IMGNAME=$(echo "$file" | cut -d'.' -f1)
if test -z $3
then
EXTENSION=$(echo "$file" | cut -d'.' -f2)
convert $1/$file -resize $2 -quality 100 $1/$IMGNAME-$2.$EXTENSION
echo "$file => $IMGNAME-$2.$EXTENSION"
else
convert $1/$file -resize $2 -quality 100 $1/$IMGNAME-$2.$3
echo "$file => $IMGNAME-$2.$3"
fi
done
Here is the current script:
# !/bin/bash
# resize [pattern] [sizeXxsizeY] [outputformat]
# if [outputformat] 开发者_JS百科is omitted, the input file format is assumed
for file in $(echo $1)
do
IMGNAME=$(echo "$file" | cut -d'.' -f1)
if test -z $3 && if test -f $3
then
EXTENSION=$(echo "$file" | cut -d'.' -f2)
convert $file -resize $2 -quality 100 $IMGNAME-$2.$EXTENSION
echo "$file => $IMGNAME-$2.$EXTENSION"
else
convert $file -resize $2 -quality 100 $IMGNAME-$2.$3
echo "$file => $IMGNAME-$2.$3"
fi
done
Given the command resize * 400x400
, convert throws an error as it cannot process .DS_Store (a hidden file residing in every file on an OSX system). As I will never be processing hidden images, I would like to automatically filter them. I've been trying to do this with grep or find, but I haven't figured it out yet.
New script goes here:
for file in $(echo $1)
do
I would suggest changing the commandline of your script from resize * 400x400
to resize 400x400 *
, the script would be more like the standard unix tools that way (grep
, sed
, ln
, etc.). You would not have to unset the dotglob option in your script (which is better since it's up to the user of the script if he wants hidden files globbed or not).
Your script would look something like this:
#!/bin/bash
OUTPUTFORMAT=$1
# Remove original $1 from the list of arguments
shift
for i in "$@"
do
# Use $OUTPUTFORMAT here
etc....
If you do not want to change the commandline for your script. You could try setting GLOBIGNORE
export GLOBIGNORE=".*"
Or if extglob
is set you could try file globbing like so:
echo !(.*)
There is a dotglob
shell option that decides if files starting with .
are included when globbing. You can check if this is the case with
shopt dotglob
You also can explicitly disable it in your script:
#!/bin/bash
shopt -u dotglob
for file in $1/*; do
...
done
there's no need to use ls with a for loop, most of the time its useless. also the for loop with * doesn't return hidden files, unless you specifically specify it. To show hidden files,
for files in .*
do
echo $files
done
as you are getting a list of files in $* you can check them one by one
for i in $*
do
expr $i : '^\..*' > /dev/null && continue
# process file
done
精彩评论