In bash, is there a better solution for iterating through a directory and modifying a single character in some folders?

Viewed 32

On Bash, I used the following script to replace the empty spaces in some directories with an underscore:

for dir in */; do
mv "${dir}" "${dir// /_}"
done

This did the trick but still received unnecessary output for directories that did not have an empty space to be replaced:

mv: cannot move 'directory1' to a subdirectory of itself, 'directory1/directory1'

Is there a more succinct way to carry this out in bash that doesn't result in a message for each of those directories that was unaffected?

Thanks

2 Answers

Simply replace

for dir in */

with

for dir in *\ */

You may also consider setting nullglob option (shopt -s nullglob) before the for loop.

You may like to consider using a command line tool designed for this kind of task. Two I regularly use are rename and detox.

$ mkdir -p 'foo bar/bar foo'
$ rename --nono --fullpath 's/\s+/_/' *
rename(foo bar, foo_bar)
$ detox --dry-run *
foo bar -> foo_bar
foo bar/bar foo -> foo bar/bar_foo

Note that rename is not recursive whereas detox is. Rename is a perl program so you can use PCRE regexes.

If you need to recurse with rename you can do the following:

$ shopt -s globstar
$ rename --nono --fullpath 's/\s+/_/' **
rename(foo bar, foo_bar)
rename(foo bar/bar foo, foo_bar/bar foo)
Related