How to zero pad numbers in file names in Bash?

2020-01-27 11:41发布

What is the best way, using Bash, to rename files in the form:

(foo1, foo2, ..., foo1300, ..., fooN)

With zero-padded file names:

(foo00001, foo00002, ..., foo01300, ..., fooN)

标签: bash rename
9条回答
够拽才男人
2楼-- · 2020-01-27 12:15

The following will do it:

for ((i=1; i<=N; i++)) ; do mv foo$i `printf foo%05d $i` ; done

EDIT: changed to use ((i=1,...)), thanks mweerden!

查看更多
做自己的国王
3楼-- · 2020-01-27 12:17

To left-pad numbers in filenames:

$ ls -l
total 0
-rw-r--r-- 1 victoria victoria 0 Mar 28 17:24 010
-rw-r--r-- 1 victoria victoria 0 Mar 28 18:09 050
-rw-r--r-- 1 victoria victoria 0 Mar 28 17:23 050.zzz
-rw-r--r-- 1 victoria victoria 0 Mar 28 17:24 10
-rw-r--r-- 1 victoria victoria 0 Mar 28 17:23 1.zzz

$ for f in [0-9]*.[a-z]*; do tmp=`echo $f | awk -F. '{printf "%04d.%s\n", $1, $2}'`; mv "$f" "$tmp"; done;

$ ls -l
total 0
-rw-r--r-- 1 victoria victoria 0 Mar 28 17:23 0001.zzz
-rw-r--r-- 1 victoria victoria 0 Mar 28 17:23 0050.zzz
-rw-r--r-- 1 victoria victoria 0 Mar 28 17:24 010
-rw-r--r-- 1 victoria victoria 0 Mar 28 18:09 050
-rw-r--r-- 1 victoria victoria 0 Mar 28 17:24 10

Explanation

for f in [0-9]*.[a-z]*; do tmp=`echo $f | \
awk -F. '{printf "%04d.%s\n", $1, $2}'`; mv "$f" "$tmp"; done;
  • note the backticks: `echo ... $2}\` (The backslash, \, immediately above just splits that one-liner over two lines for readability)
  • in a loop find files that are named as numbers with lowercase alphabet extensions: [0-9]*.[a-z]*
  • echo that filename ($f) to pass it to awk
  • -F. : awk field separator, a period (.): if matched, separates the file names as two fields ($1 = number; $2 = extension)
  • format with printf: print first field ($1, the number part) as 4 digits (%04d), then print the period, then print the second field ($2: the extension) as a string (%s). All of that is assigned to the $tmp variable
  • lastly, move the source file ($f) to the new filename ($tmp)
查看更多
疯言疯语
4楼-- · 2020-01-27 12:22

Here's a quick solution that assumes a fixed length prefix (your "foo") and fixed length padding. If you need more flexibility, maybe this will at least be a helpful starting point.

#!/bin/bash

# some test data
files="foo1
foo2
foo100
foo200
foo9999"

for f in $files; do
    prefix=`echo "$f" | cut -c 1-3`        # chars 1-3 = "foo"
    number=`echo "$f" | cut -c 4-`         # chars 4-end = the number
    printf "%s%04d\n" "$prefix" "$number"
done
查看更多
登录 后发表回答