web-dev-qa-db-ja.com

ファイル名に先行ゼロを追加するLinuxシェルスクリプト

約1,700個のファイルがあるフォルダーがあります。それらはすべて1.txt1497.txtなどのように名前が付けられています。すべてのファイルの名前を変更して、すべてのファイル名が4桁になるようにします。

つまり、23.txt0023.txtになります。

これを行うシェルスクリプトとは何ですか?または関連する質問:grepを使用して、\d.txt(つまり、1桁、ピリオド、txt)を含む行のみを一致させるにはどうすればよいですか?

ここに私が持っているものがあります:

for a in [command i need help with]
do
  mv $a 000$a
done

基本的に、1桁、2桁、および3桁のファイル名を検索するコマンドを使用して、3回実行します(最初のゼロの数を変更します)。

53
David Oneill

試してください:

for a in [0-9]*.txt; do
    mv $a `printf %04d.%s ${a%.*} ${a##*.}`
done

ファイル名のパターンを変更する([0-9]*.txt) 必要に応じて。


ファイル名の初期セットに関する仮定を行わない、汎用の列挙された名前変更:

X=1;
for i in *.txt; do
  mv $i $(printf %04d.%s ${X%.*} ${i##*.})
  let X="$X+1"
done

同じトピック:

48
Colin Hebert

Perlとともにインストールされることがあるrename(場合によってはprename)スクリプトを使用すると、Perl式を使用して名前を変更できます。名前の衝突がある場合、スクリプトは名前の変更をスキップします。

以下のコマンドは、4桁以下の拡張子に「.txt」が続くファイルのみの名前を変更します。そのパターンに厳密に準拠していないファイルの名前は変更しません。 4桁を超える数字で構成される名前は切り捨てられません。

rename 'unless (/0+[0-9]{4}.txt/) {s/^([0-9]{1,3}\.txt)$/000$1/g;s/0*([0-9]{4}\..*)/$1/}' *

いくつかの例:

Original    Becomes
1.txt       0001.txt
02.txt      0002.txt
123.txt     0123.txt
00000.txt   00000.txt
1.23.txt    1.23.txt

これまでに与えられた他の回答は、パターンに適合しないファイルの名前変更を試み、数字以外の文字を含むファイル名のエラーを生成し、名前の衝突を引き起こす名前変更を実行し、名前にスペースを含むファイルの名前変更を試行し、失敗しますおそらく他の問題。

14
for a in *.txt; do
  b=$(printf %04d.txt ${a%.txt})
  if [ $a != $b ]; then
    mv $a $b
  fi
done
12

ワンライナー:

ls | awk '/^([0-9]+)\.txt$/ { printf("%s %04d.txt\n", $0, $1) }' | xargs -n2 mv

Grepを使用して\ d.txt(IE 1桁、ピリオド、文字txt)を含む行のみを一致させるにはどうすればよいですか?

grep -E '^[0-9]\.txt$'
9
rkhayrov

フォルダーにデータ型.datのファイルがあると仮定しましょう。このコードをrun.shという名前のファイルにコピーし、chmode +x run.shを実行して実行可能にし、./run.shを使用して実行します。

#!/bin/bash
num=0
for i in *.dat
do

  a=`printf "%05d" $num`
  mv "$i" "filename_$a.dat"
  let "num = $(($num + 1))"
done

これにより、フォルダー内のすべてのファイルがfilename_00000.datfilename_00001.datなどに変換されます。

4
sinner

このバージョンでは、数値の前(後)の文字列の処理もサポートしています。ただし、基本的には、awkがサポートしている限り、任意の正規表現マッチング+ printfを実行できます。また、ファイル名の空白文字(改行を除く)もサポートしています。

for f in *.txt ;do
    mv "$f" "$( 
        awk -v f="$f" '{
            if ( match(f, /^([a-zA-Z_-]*)([0-9]+)(\..+)/, a)) {
                printf("%s%04d%s", a[1], a[2], a[3])
            } else {
                print(f)
            }
        }' <<<''
    )"
done
1

1桁のテキストファイルのみを一致させるには、次のことができます。

$ ls | grep '[0-9]\.txt'
0
LukeN

ワンライナーヒント:

while [ -f ./result/result`printf "%03d" $a`.txt ]; do a=$((a+1));done
RESULT=result/result`printf "%03d" $a`.txt
0
kayn

スペースを含むファイル名が存在する場合でも、慎重に正しいソリューションを提供するには:

#!/usr/bin/env bash

pattern='%04d'  # pad with four digits: change this to taste

# enable extglob syntax: +([[:digit:]]) means "one or more digits"
# enable the nullglob flag: If no matches exist, a glob returns nothing (not itself).
shopt -s extglob nullglob

for f in [[:digit:]]*; do               # iterate over filenames that start with digits
  suffix=${f##+([[:digit:]])}           # find the suffix (everything after the last digit)
  number=${f%"$suffix"}                 # find the number (everything before the suffix)
  printf -v new "$pattern" "$number" "$suffix"  # pad the number, then append the suffix
  if [[ $f != "$new" ]]; then                   # if the result differs from the old name
    mv -- "$f" "$new"                           # ...then rename the file.
  fi
done
0
Charles Duffy