Bash - Adding 0's in the middle of a file name

2019-07-20 13:40发布

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.

标签: bash shell
4条回答
小情绪 Triste *
2楼-- · 2019-07-20 13:59

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/"
查看更多
做个烂人
3楼-- · 2019-07-20 14:01

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
查看更多
Juvenile、少年°
4楼-- · 2019-07-20 14:10

The ls provided by GNU coreutils supports version sort:

$ ls -v
mem0.csv
mem1.csv
mem2.csv
...
mem10.csv
...
查看更多
forever°为你锁心
5楼-- · 2019-07-20 14:19

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
查看更多
登录 后发表回答