giobrach
giobrach

Reputation: 135

Bash command ls ordering options

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

Answers (1)

whites11
whites11

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

Related Questions