[prog] Bash script blues

Wolfgang Petzold petzold at villa-chaos.de
Thu Aug 25 20:15:57 EST 2005


Kaitlyn:
>     What I was trying was this:
> 
>     [code] for i in `ls -1 $HOUSE |grep .torrent` ; do mv "$i" `echo 
> "$i" |sed s/\ /_/g` ; done [/code] (House is equated in the first part 
> of the script)
> 
> However I get errors:
> mv: cannot stat `this': No such file or directory
> mv: cannot stat `is': No such file or directory
> mv: cannot stat `torrent.torrent': No such file or directory

Yes, I admit, that would have been my first try, too.

I found that a while/read loop works with the way you collected the file
names:

$ ls -1 $HOUSE | grep .torrent | while read filename ; do \
	mv "$filename" `echo "$filename" | sed -e 's/ /_/g;'` \
done

"read var" takes a line of input from stdin and puts the line
into $var. I've always found the "while read var" construction somewhat
confusing, but, however, it works ... "read" seems to return an
"unsuccessful" return value when it only finds an End-of-file
(End-of-text, whatever) character, which will then end the "while" loop.

This "while read" loop will also work if you have a file with the
relevant filenames in it, say

$ ls -1 $HOUSE | grep .torrent >my_files
$ [find some more .torrent files] >>my_files
$ while read filename ; do \
	mv "$filename" `echo "$filename" | sed -e 's/ /_/g;'` \
  done <my_files

Moreover, I personally would use "find" instead of "ls|grep".

(If I hadn't thought "There must be some way to do this job in bash!" I
would probably have used perl as well ... :-)

All the best,
Wolfgang


More information about the Programming mailing list