Reputation: 390
I'm trying to write a shell script to cleanup a directory by deleting files that match particular patterns. My code works with all patterns but if the file name starts with space. Although we can delete a file starting with space by rm \ *
however if I pass this pattern to my script it won't delete files starting with space. Here is my code:
for file in *;do
for pattern in $*; do
if [[ -f "$file" && "$file" == $pattern ]]; then
rm "$file"
fi
done
done
I also tried this simpler code, but the same problem!
for pattern in $*; do
if [[ -f $pattern ]]; then
rm $pattern
fi
done
Could you please help me why there is a problem just with files starting with space?!
Upvotes: 1
Views: 867
Reputation: 390
for file in *;do
for pattern in "$@"; do
if [[ -f "$file" && "$file" == $pattern ]]; then
rm "$file"
fi
done
done
If we simply change $@ to quoted "$@" then each individual argument would be wrapped in double quotation and no space would be lost. On the other hand we need a quoted string at the right of == operator, because when the '==' operator is used inside [[ ]], the string to the right of the operator is considered a pattern. But here we will not quote $pattern since all arguments in the list include double quotation.
Upvotes: 0
Reputation: 1317
this is really a challenging one for starters please see below example
[shravan@localhost mydir]$ ls " myfile"
myfile
[shravan@localhost mydir]$ echo $vr1
" myfile"
[shravan@localhost mydir]$ ls $vr1
ls: ": No such file or directory
ls: myfile": No such file or directory
[shravan@localhost mydir]$ vr2=" myfile"
[shravan@localhost mydir]$ echo $vr2
myfile
You can see above that ls " myfile" is working but it is not working after assigning this value in variable vr1 or vr2. So we cannot do check of file if it exists or not.
For solution keep all you patterns in a file and all patterns in double quotes. see example below.
[shravan@localhost mydir]$ touch " myfile"
[shravan@localhost mydir]$ touch my.pl
[shravan@localhost mydir]$ ls
exe.sh findrm inp input myfile my.pl pattern text text1
[shravan@localhost mydir]$ cat inp
" myfile"
"my.pl"
[shravan@localhost mydir]$ cat inp | xargs rm
[shravan@localhost mydir]$ ls
exe.sh findrm inp input pattern text text1
The files are removed. Or if you have lot of patterns and dont want to add quotes to them use below.
cat inp | awk '{print "\""$0"\""}' | xargs rm
Yes if file is not found then it will give error for that file that
rm: cannot remove ` myfile': No such file or directory
Upvotes: 0
Reputation: 54465
Rather than $*
, if you use the special parameter $@
, the items in the list will start with quotes around them. You still have to quote the variables where you use them.
Reworking the second example, that would be
for pattern in "$@"; do
if [[ -f "$pattern" ]]; then
rm -f "$pattern"
fi
done
Upvotes: 1