I Dabble
I Dabble

Reputation: 331

Remove all dots from directory name (shell)

I've found several answers that look like they should work, but when I run a script to try and remove dots from directory names, the dots seem to confuse the script regardless of quoting. For instance, I have tried this on a directory named s. om. e dir (25):

for dir in $(find . -type d -maxdepth 1 -name *.*); do
    mv "$dir" `echo "$dir" | tr '.' '_'`
done

and get this output in the terminal:

mv: rename ./s. to _/s_: No such file or directory
mv: rename om. to om_: No such file or directory
mv: rename e to e: No such file or directory
mv: rename dir to dir: No such file or directory
mv: rename (25) to (25): No such file or directory

How can I rename the directory from s. om. e dir (25) to s_ om_ e dir (25) without the code breaking at each instance of a dot?

Upvotes: 2

Views: 1472

Answers (2)

anubhava
anubhava

Reputation: 785781

Instead of echo | tr, you can simply use parameter substitution:

mv -- "$dir" "${dir//./_}"

You should use a while loop instead of a for loop in a process substitution:

while IFS= read -r -d '' dir; do
    mv -- "$dir" "${dir//./_}"
done < <(find . -type d -maxdepth 1 -name '*.*' -print0)

You should also quote your file pattern in find.

Moreover, since you're only iterating directories in the current directory, you can use this glob:

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

Upvotes: 3

melpomene
melpomene

Reputation: 85867

The problem is using for/in on the output of find.

If you have the Perl version of rename, you can simply do

rename 'tr/./_/' *.*/

Otherwise,

for i in *.*; do
    [ -d "$i" ] || continue
    mv -- "$i" "${i//./_}"
done

should work.

Upvotes: 4

Related Questions