Bash recursively replace many spaces with names
Can anyone recommend a safe solution for recursively replacing spaces with underscores in file and directory names starting at a given root directory? For example,
$ tree ... | - a dir | `- file with spaces.txt `- b dir | - another file with spaces.txt `- yet another file with spaces.pdf
becomes:
$ tree ... | - a_dir | `- file_with_spaces.txt `- b_dir | - another_file_with_spaces.txt `- yet_another_file_with_spaces.pdf
I copied the question by another user, which is the main question, but I need to add another problem:
I am using the following solution:
$ find -depth -name '* *' -execdir rename " " "_" {} +;
It works, but only replaces the first whitespace found on an element (dir or file). Any ideas on how to create a loop to find spaces and stop when they go away?
If you don't have one rename
available, or if you're not sure which version you have, here's a way to achieve it:
find . -depth -name '* *' -execdir bash -c 'for i; do mv "$i" "${i// /_}"; done' _ {} +
You can use:
find . -depth -name '* *' -execdir rename 's/ /_/g' {} +
Here's a solution without rename
find -type d -name "* *" -print | awk '{print;gsub(" ","_",$0);print}' | xargs -r -n2 -d "\n" mv
find -name "* *" -print | awk '{print;gsub(" ","_",$0);print}' | xargs -r -n2 -d "\n" mv
I am assuming there is no \n
.
You can also change the variable IFS
to IFS
use line endings instead of spaces in the loop:
IFS=$(echo -en "\n\b") ; for file in $(find . -type f) ; do mv -v $file ${file// /_} ; done
https://www.cyberciti.biz/tips/handling-filenames-with-spaces-in-bash.html
Thanks to Jokki for his input. The only one I tried worked recursively.