Reputation: 135
New here (and to coding). I'm writing a simple bash script that helps me change a character into another character in all files of the current directory. Here's the code:
#!/bin/bash
#this script changes characters in all files of the current directory
NUM=$(ls -1 | wc -l | awk '{print $1}')
echo "There are $NUM files in this folder."
echo "Changing $1 to $2 in all their names..."
echo "Done! Here's what happened:"
for i in $(seq 1 $NUM)
do
OLDNAME=$(ls -1 | head -$i | tail -1)
NEWNAME=$(ls -1 | head -$i | tail -1 | sed -e "s/${1}/${2}/g")
mv -v "$OLDNAME" "$NEWNAME"
done
So if I write ./ccin.sh " " "_"
it should be changing all spaces in the names of all files in the current directory to underscores. Except it doesn't, and I think this is ls
's fault. The for
loop is skipping over some files because ls
changes the order according to which it sorts the files every time mv
effectively modifies one of them. So I would need to isolate the names of the files in a way that does not rely on the "last modified" property. I thought of file size, but that won't work if there are two files that have the same size – e.g., I'm trying this code on a directory full of empty files.
Is there a way to sort files with ls
such that they remain in the same order as mv
modifies their names?
Upvotes: 0
Views: 255
Reputation: 13300
You can try to substitute your for loop with this one:
find . -type f | while read file
do
OLDNAME="$file"
NEWNAME=`echo $file| sed -e "s/${1}/${2}/g"`
mv -v "$OLDNAME" "$NEWNAME"
done
Instead of running ls
multiple times in order to get the file to rename, you run find only once and iterate over the results
Upvotes: 1