0

I'm using the following shell script to loop through a text file, then delete anything that matches the filename there.

However, it does not work if the filename has spaces in it. How can this be rectified? Ideally my script will find and delete filenames with and without spaces....

Any other improvements to this most appreciated.

This is in OSX

Thanks for your ideas and suggestions in advance,

Dan

$ cat delete-files.sh
#!/bin/sh

PATH=/bin:/usr/bin:/usr/sbin
export PATH

for i in `cat /opt/scripts/files-to-delete.dat` ;

do find /Volumes/folder/subfolder -iname $i -print -delete ;

done

And the text file:

$ cat files-to-delete.dat
LloydsTSB_Customer_Identification.html
Santander_Update_Process.html
asdasdasd asdasdasd.txt
Dan
  • 931
  • 2
  • 18
  • 31
  • `IFS=$'\n'; for l in $(cat)` performs pathname expansion, and `while IFS= read -r l` skips the last line if the file doesn't end with a linefeed. See [this answer](http://stackoverflow.com/questions/10748703/iterate-over-lines-instead-of-words-in-a-for-loop-of-shell-script/16145728#16145728). – Lri Apr 23 '13 at 23:38

3 Answers3

4

The input file is being read in assuming that whitespace is the field separator. Change it to newline like so:

#!/bin/sh

PATH=/bin:/usr/bin:/usr/sbin
export PATH

IFS=$'\n'

for i in `cat /opt/scripts/files-to-delete.dat` ;

do find /Volumes/folder/subfolder -iname $i -print -delete ;

done

Note the added IFS=$'\n' line.

btanaka
  • 382
  • 2
  • 6
  • +1: Of course, this now transfers the problem to file names that contain a newline, but fortunately they're a lot rarer than names with spaces in them. The semicolon after the `for` and `do` lines are superfluous (though I note they are in the question too; they're superfluous there, too!). – Jonathan Leffler Apr 23 '13 at 22:39
  • @btanaka thank you, this is perfect. And it makes sense as well. Thanks! – Dan Apr 23 '13 at 22:52
  • @JonathanLeffler, you are correct. I simply left the original script intact and added the IFS assignment. Probably would have been more helpful in a larger sense to re-write the script more correctly. In any case, you're right! – btanaka Apr 23 '13 at 23:50
3

for i in $(cat filenames) is a Bad Idea, for precisely the reasons you're running into. Lots more information can be found here and here, but in short:

while IFS= read -r line; do stuff_with "$line"; done < "$file"

is always the right solution. (Note: This will still fail if any of your filenames contain newlines; in which case, it's probably easier to delete them yourself.)

0

Thanks to Lauri Ranta for pointing me to the most elegant solution:

#!/bin/sh

PATH=/bin:/usr/bin:/usr/sbin
export PATH

while IFS= read -r line

do find /Volumes/folder/subfolder -iname "$line" -print -delete

done < "/tmp/files-to-delete.dat"
Dan
  • 931
  • 2
  • 18
  • 31