作成時間に基づいて数値順を使用して、ディレクトリ内のすべてのファイル名を変更します。

作成時間に基づいて数値順を使用して、ディレクトリ内のすべてのファイル名を変更します。

~/folder/ contain (最新のファイルから最も古いファイルまで) と同じディレクトリにあるすべてのファイルの名前を変更しようとしています: apple.foo, Pie.foo, cookie.foo, melon.foo

固定プレフィックスと数字001を使用して名前を変更します。最も古い999に増加

melon.foo >> object001.foo

Cookie.foo >> object002.foo

パイ.foo >> object003.foo

apple.foo >> object004.foo

誰でもこれを達成する方法を知っていますか?

答え1

zshシェルの使用:

counter=0

for name in $HOME/folder/*(.NDOm); do
    counter=$(( counter + 1 ))

    suffix=$name:e
    printf -v newname '%s/object%.3d%s' $name:h $counter ${suffix:+.$suffix}

    mv $name $newname
done

~/folderこれは、最後に変更されたタイムスタンプに基づいて、最も古いものから最新のものまで、ディレクトリ内の一般ファイルのすべての名前を繰り返します。各名前に対して、現在の名前のディレクトリ部分とカウンタを使用して新しい名前を設定します。ファイル名が新しい名前に変更されます(確認は不要、名前の競合の確認はありません)。

このprintf -v newname呼び出しは出力を変数として「印刷」しますnewname。書式文字列は、3つの位置(たとえば、等)に%.3dゼロで埋められた整数を出力します。001パラメータ拡張は、パス名のヘッダー/ディレクトリ部分に拡張されます(同じ)。023109$name:h$namedirname "$name"

元のファイル名(つまり、現在のファイルが)に拡張される$name:e「拡張子」はに保存されます。ファイル拡張子がある場合は、前にドットを追加します。fooapple.foosuffix${suffix:+.$suffix}

ファイル名ワイルドカードパターンの末尾のinは、古いワイルドカードパターンが通常のファイルにのみ一致するようにするワイルドカード文字です.。パターンがシェルに設定されているかのように動作するようにします(.NDOm)(一致するものがない場合は、何も展開せずに結果に隠された名前を含めます)。最も古い(最も最近変更された)ファイルが最初にソートされるように、一致する名前をソートします。NDnullglobdotglobbashOm

ログインシェルでない場合は、zshスクリプトとして実行できます。

$ zsh ./this-script

答え2

bashこれは、構文解析を必要とせlsず、法的に名前付きのすべてのファイル(挿入スペース、句読点、改行文字など)を処理できるGNUユーティリティで書かれたバージョンです。

#!/bin/bash
k=0                                               # start at the beginning
find *.foo -type f -printf "%T@ %p\0" |           # list all the files with modification time
    sort -z |                                     # sort by increasing modification time
    cut -z -d' ' -f2- |                           # discard the time value leaving just the name
    while IFS= read -r -d '' file                 # now loop for each file...
    do
        ((++k))                                   # next count
        seq=$(printf "%03d" $k)                   # format the three-digit counter
        name="${file%.*}" ext="${file##*.}"       # split filename into name and extension
        echo will mv "$file" "$name.$seq.$ext"    # show what would happen without doing it
    done

echo willmvコマンドを実行する準備ができたら削除します。

はい

# preparation
for f in {melon,cookie,pie,apple}.foo; do touch "$f"; sleep 1; done

# list in order of modification time (oldest to newest)
ls -tr
melon.foo  cookie.foo  pie.foo  apple.foo

# run the script and observe the output
k=0; find *.foo -type f -printf "%T@ %p\0" | sort -z | cut -z -d' ' -f2- | while IFS= read -r -d '' file; do ((++k)); seq=$(printf "%03d" $k); name="${file%.*}" ext="${file##*.}"; echo mv "$file" "$name.$seq.$ext"; done

will mv melon.foo melon.001.foo
will mv cookie.foo cookie.002.foo
will mv pie.foo pie.003.foo
will mv apple.foo apple.004.foo

答え3

ファイル名にスペース、タブ、または改行が含まれていないと仮定すると、1行と1行をbash使用するのはawk簡単です。

ls -rt | awk -F "." '{print  $0 " object" sprintf("%03d",NR)  "." $NF }' | xargs -L 1 mv

このコマンドは各行に対して実行されますxargs -lmvコマンドを実行する前に、次のコマンドを実行して、ターゲットファイル名とソースファイル名が正しいことを確認してください。

ls -rt | awk -F "." '{print  $0 " object" sprintf("%03d",NR)  "." $NF }'

出力は次のようになります。

melon.foo object001.foo
cookie.foo object002.foo
pie.foo object003.foo
apple.foo object004.foo

関連情報