60

Bashを使用して、次の形式でファイルの名前を変更する最良の方法は何ですか:

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

ファイル名をゼロで埋めた場合:

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

10 に答える 10

74

これは純粋な bash ではありませんが、次の Perl バージョンを使用するとはるかに簡単になりrenameます。

rename 's/\d+/sprintf("%05d",$&)/e' foo*

's/\d+/sprintf("%05d",$&)/e'Perl 置換正規表現はどこにありますか。

  • \d+数字の最初のセット (少なくとも 1 つの数字) と一致します
  • sprintf("%05d",$&)一致した数字を Perl の に渡し、sprintf5%05d桁にパディングします
于 2010-12-30T10:23:45.687 に答える
40

Nアプリオリに修正されていない場合:

for f in foo[0-9]*; do
  mv "$f" "$(printf 'foo%05d' "${f#foo}")"
done
于 2008-09-11T03:47:46.070 に答える
21

ファイル名に接頭辞だけでなく接尾辞もある、より複雑なケースがありました。また、ファイル名から数値を減算する必要がありました。

たとえば、私はなりたかっfoo56.pngfoo00000055.png

もっと複雑なことをしているなら、これが役立つことを願っています。

#!/bin/bash

prefix="foo"
postfix=".png"
targetDir="../newframes"
paddingLength=8

for file in ${prefix}[0-9]*${postfix}; do
  # strip the prefix off the file name
  postfile=${file#$prefix}
  # strip the postfix off the file name
  number=${postfile%$postfix}
  # subtract 1 from the resulting number
  i=$((number-1))
  # copy to a new name with padded zeros in a new folder
  cp ${file} "$targetDir"/$(printf $prefix%0${paddingLength}d$postfix $i)
done
于 2010-09-13T11:54:54.573 に答える
6

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)
于 2019-03-29T01:07:23.197 に答える
5

純粋なBash、「mv」以外の外部プロセスはありません:

for file in foo*; do
  newnumber='00000'${file#foo}      # get number, pack with zeros
  newnumber=${newnumber:(-5)}       # the last five characters
  mv $file foo$newnumber            # rename
done
于 2009-02-03T08:43:45.170 に答える
2

次のようにします。

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

編集: ((i=1,...)) を使用するように変更されました。mweerdenに感謝します。

于 2008-09-11T03:41:38.737 に答える
1

この回答は、Chris Conway の受け入れられた回答から派生したものですが、ファイルに拡張子があることを前提としています(Chris の回答とは異なります)。この (かなり長い) 1 つのライナーをコマンド ラインに貼り付けるだけです。

for f in foo[0-9]*; do mv "$f" "$(printf 'foo%05d' "${f#foo}" 2> /dev/null)"; done; for f in foo[0-9]*; do mv "$f" "$f.ext"; done;

オプションの追加情報

このスクリプトは名前を変更します

foo1.ext    > foo00001.ext
foo2.ext    > foo00002.ext
foo1300.ext > foo01300.ext

マシンでテストするには、この 1 つのライナーをEMPTYディレクトリに貼り付けます。

rm * 2> /dev/null; touch foo1.ext foo2.ext foo1300.ext; for f in foo[0-9]*; do mv "$f" "$(printf 'foo%05d' "${f#foo}" 2> /dev/null)"; done; for f in foo[0-9]*; do mv "$f" "$f.ext"; done;

これにより、ディレクトリの内容が削除され、上記の例のファイルが作成されてから、一括で名前が変更されます。

ワンライナーが必要ない人のために、インデントされたスクリプトは次のようになります。

for f in foo[0-9]*;
  do mv "$f" "$(printf 'foo%05d' "${f#foo}" 2> /dev/null)";
done;

for f in foo[0-9]*;
  do mv "$f" "$f.ext";
done;
于 2021-09-03T01:59:06.040 に答える
0

これは、固定長のプレフィックス (「foo」) と固定長のパディングを想定した簡単な解決策です。もっと柔軟性が必要な場合は、少なくともこれが出発点として役立つでしょう。

#!/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
于 2008-09-11T03:43:43.677 に答える