ファイル名を埋め込んで、Unix が番号順にリストするようにする

ファイル名を埋め込んで、Unix が番号順にリストするようにする

次のようにフォーマットされた複数のファイルを含むフォルダーがあります。

C Block Scan copy 1.pdf
C Block Scan copy 2.pdf
C Block Scan copy 3.pdf
C Block Scan copy 4.pdf
.
.
.

私が抱えている問題の1つは、 を実行するとls、Unixがそれらを次のようにリストすることです。

C Block Scan copy 1.pdf
C Block Scan copy 10.pdf
C Block Scan copy 11.pdf
C Block Scan copy 12.pdf
.
.
.

Unixが(うまくいけば)次のように順番にリストするように数字を埋め込んでおきたい。

C Block Scan copy 01.pdf
C Block Scan copy 02.pdf
C Block Scan copy 03.pdf
.
.
.
C Block Scan copy 09.pdf
C Block Scan copy 10.pdf
C Block Scan copy 11.pdf
C Block Scan copy 12.pdf
.
.
.

同様の問題に関する投稿を見つけました。ファイル名の数字を固定長に埋め込むしかし、彼らの解決策を自分のケースに適用してみましたが、うまくいきませんでした。私が試したことは次のとおりです。

for f in *.pdf; do
    int=`basename $f .pdf | cut -d '.' -f 2`
    new_name=`printf "file.%0.2i.pdf\n” $int`
    [ ! -f $new_name ] && mv $f $new_name
done

これは彼らの解決策を私の状況に合わせて盲目的に適応させたものであることは認めます。私は基礎となる構文をあまり理解していないし、StackExchange でその投稿にコメントできるほど高いランクをまだ持っていないため、これは気に入りません。

私はシェル スクリプトの初心者なので、構文の意味を説明していただけると助かります。

参考になれば幸いですが、私は macOS Mojave 10.14.6 を使用しており、Brew がインストールされています。

前もって感謝します。

答え1

zsh(現在 macOS のデフォルトのユーザー シェル)を使用する場合:

autoload zmv # best in ~/.zshrc
zmv '(* )([0-9].pdf)' '${1}0$2'

答え2

これにより、現在のディレクトリ内で、質問で説明されているパターンに従って名前が付けられたすべての「*.pdf」ファイルが検索され、同じ名前で数字が 2 桁に埋め込まれた名前に変更されます。

#!/usr/bin/env bash

shopt -s nullglob

for f in *[[:space:]][0-9].pdf; do
    int="$(basename "$f" | rev | cut -d ' ' -f1 | rev | cut -d . -f1)"
    name="$(basename "$f" | rev | cut -d ' ' -f2- | rev)"
    padded_int="$(printf "%02d\n" "$int")"

    echo mv "$f" "$(printf "%s %s.pdf" "$name" "$padded_int")"

done

実際に実行するecho前に削除しますが、まずはそのまま実行して、目的の動作が実行されることを確認します。上記のスクリプトを次の場所に保存した場合の使用例:mvmvpdf.sh

$ for i in {1..10}; do touch "C Block Scan copy $i.pdf"; done
$ ./pdf.sh
mv C Block Scan copy 1.pdf C Block Scan copy 01.pdf
mv C Block Scan copy 2.pdf C Block Scan copy 02.pdf
mv C Block Scan copy 3.pdf C Block Scan copy 03.pdf
mv C Block Scan copy 4.pdf C Block Scan copy 04.pdf
mv C Block Scan copy 5.pdf C Block Scan copy 05.pdf
mv C Block Scan copy 6.pdf C Block Scan copy 06.pdf
mv C Block Scan copy 7.pdf C Block Scan copy 07.pdf
mv C Block Scan copy 8.pdf C Block Scan copy 08.pdf
mv C Block Scan copy 9.pdf C Block Scan copy 09.pdf

最初の行:

#!/usr/bin/env bash

シバンさらに、私envその特徴

この行

shopt -s nullglob

セットヌルグロブ シェルオプション リンク先のサイトでも説明されています:

nullglob

If set, Bash allows filename patterns which match no files to
expand to a null string, rather than themselves.

パターン基準に一致するファイルがない場合に for ループが開始されないようにするために必要です。

for f in *[[:space:]][0-9].pdf; do

*[[:space:]][0-9].pdfは、任意の数の文字の後に空白文字が続き、数字が1つ続き、末尾に次の文字が続く名前を持つファイルを検索するシェルパターンです。.pdfループ内には、$f処理された .pdf ファイルの名前が保持されます。

ここ

int="$(basename "$f" | rev | cut -d ' ' -f1 | rev | cut -d . -f1)"

を使用しておりますコマンド置換 指定されたファイル名の整数部分を変数に割り当てます。basenameで何が行われているかを確認しman basename、ターミナルでパイプラインを再現することができます。

$ f='C Block Scan copy 1.pdf'
$ echo basename "$f" | rev | cut -d ' ' -f1 | rev | cut -d . -f1
1
$ f='C Block Scan copy 5.pdf'
$ echo basename "$f" | rev | cut -d ' ' -f1 | rev | cut -d . -f1
5

$ここにはコマンドラインプロンプト コマンドの一部ではなく、新しい行の開始を示すために使用されます。

次の行

name="$(basename "$f" | rev | cut -d ' ' -f2- | rev)"

.pdf の名前の部分、つまり番号より前の部分を抽出します。

次の行

padded_int="$(printf "%02d\n" "$int")"

Bashの組み込みprintfコマンドを使用して$int、それをパディングし、という変数に保存しますpadded_int。ループの最後の行で

echo mv "$f" "$(printf "%s %s.pdf" "$name" "$padded_int")"

echoコマンド置換を使用して実際の名前変更をprintf 再度実行します (もちろん実行しません)。は、C と同様に、printf2 つの書式指定子と 2 つの対応する引数とともに使用されます。%s

最後の行

done

ループを閉じます。

答え3

PE パラメータ拡張を使用します。シェルmvからの外部ツールのみbash

#!/usr/bin/env bash

shopt -s nullglob

for f in *[[:space:]][0-9].pdf; do
  n=${f##* }  ##: Remain only 1.pdf, 2.pdf etc.
  n=0${n%.*}  ##: Remain only 1 , 2 etc. and pad 0 so it will be 01, 02 ..
  echo mv -v "$f" "${f/[0-9]/"$n"}"  ##: Replace all [0-9] with the value of "$n"
done

関連情報