
次のようにフォーマットされた複数のファイルを含むフォルダーがあります。
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
前に削除しますが、まずはそのまま実行して、目的の動作が実行されることを確認します。上記のスクリプトを次の場所に保存した場合の使用例:mv
mv
pdf.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
この行
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 と同様に、printf
2 つの書式指定子と 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
- 見るパラメータ拡張