填充文件名,以便 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 . . .
我遇到的一個問題是,當我執行時
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 . . .
我發現了一個有類似問題的文章,Padding a number in a filename to a fixed length,但我嘗試將他們的解決方案應用於我的案例,但我無法讓它工作。這是我嘗試過的:
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 上的排名還不夠高,無法評論該文章.
我是 shell 腳本的新手,所以對語法含義的解釋會很有幫助和讚賞。
如果有幫助,我正在使用 macOS Mojave 10.14.6,並且我已經安裝了 Brew。
提前致謝。
這將在目前目錄中查找並重命名所有“*.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 shell 選項 ,該選項也在連結站點上進行了說明:
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
是一種 shell 模式,這意味著查找名稱由任意數量的字元後跟一個空格,後跟一個數字並以*.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
和命令替換。printf
與 2 個%s
格式說明符和 2 個對應參數一起使用,與 C 中類似。最後一行
done
關閉循環。
使用
zsh
(現在是 macOS 上的預設使用者 shell):autoload zmv # best in ~/.zshrc zmv '(* )([0-9].pdf)' '${1}0$2'