I have a bunch of files which are named:
mem0.csv
mem1.csv
.
.
.
.
mem153.csv
.
.
.
They are all in the same folder. When I do ls in the folder they appear in an order of
mem0.csv
mem1.csv
mem10.csv
mem100.csv
.
.
.
mem2.csv
mem20.csv
.
.
.
I want to create a bash script to push 0's between mem and the number. I figure that I need to add 0's until all the filenames are of the same length only problem is that I don't know how to do this.
The ls
provided by GNU coreutils supports version sort:
$ ls -v
mem0.csv
mem1.csv
mem2.csv
...
mem10.csv
...
You can use the printf tool, just make sure your system has it (almost all modern systems have it)
To rename them all:
for i in {1..153}; do
mv mem$i.csv mem`printf "%03d" $i`.csv
done
edit:
For a random number of files the code would become something like this:
dir = "/somedir"
fn = $(ls -l $dir | wc -l)
z = 0;
c = $fn
# Count the number of zero's to use
while [ $c -gt 0 ]; do
(( $z++ ))
c = $(( $c / 10 ))
done
# Rename the files
while [ $fn -gt 0 ]; do
mv ${dir}/mem$fn.csv ${dir}/mem$(printf "%0${z}d" $i).csv
(( $fn-- ))
done
I think ls -v (as noted by @ephemient) does what you want, but if you really have to pad the numbers with zeros, here's a quick and dirty way based on the provided filename pattern
last=$(ls -v *.csv | tail -n1) # last file has the biggest number
let max=${#last}-7 # minus the number of all the other chars (constant)
# below grep gets only the number part and head ignores the last line
# which we don't need to change
ls -v mem*.csv | egrep -o '[0-9]+' | head -n -1 | \
while read n; do
mv -ivf mem$n.csv mem$(printf "%0"$max"d" $n).csv
done
OK. Here is how I did this. I know it isn't the correct way but in this way there is a chance I'll understand stuff
#Cleaning the dest folder
cd "out"
rm *
cd ".."
#setting some variables
MAXLEN=-1
#Searching for the longest file name
for f in mem*.csv; do
LEN=${#f}
if [ $MAXLEN -lt $LEN ]; then
let MAXLEN=$LEN
fi
done
for f in mem*.csv; do
LEN=${#f}
let LEN+=1
COUNT="0"
until [ $MAXLEN -lt $LEN ]; do #Creating 0's string to add
COUNT=$COUNT"0"
let LEN+=1
done
CLEN=${#COUNT} #The string has one 0 more than it should have. We take that into an account
let CLEN-=1
echo $CLEN
if [ $CLEN != 0 ]; then
COUNT=${COUNT:0:$CLEN} #The string is to long, remove the last 0
number=$(echo $f | tr -cd '[[:digit:]]') #Extracting the number from the rest of the file name
cp $f "out/mem"$COUNT$number".csv" #creating the new file
else
cp $f "out/"$f
fi
done
ls "out/"