Command-Line

根據名稱查找文件並同時重命名移動它們

  • May 2, 2015

考慮我有根據年份命名的目錄並包含根據主題程式碼的 pdf 文件。

ls輸出是:

$ ls -l
total 32
drwxrwxrwx 1 root root 4096 Apr  8 08:52 May-June-2011
drwxrwxrwx 1 root root 4096 Apr  8 08:52 Nov-Dec-2011
drwxrwxrwx 1 root root 4096 Apr  8 20:36 Summer-2012
drwxrwxrwx 1 root root 4096 Apr  8 08:52 Summer-2013
drwxrwxrwx 1 root root 4096 Apr  8 08:52 Summer-2014
drwxrwxrwx 1 root root 4096 Apr  8 08:52 Winter-2012
drwxrwxrwx 1 root root 4096 Apr  8 08:52 Winter-2013
drwxrwxrwx 1 root root 4096 Apr  8 08:52 Winter-2014

每個目錄都包含根據主題程式碼的pdf文件:-

ls -l May-June-2011/
total 808
-rwxrwxrwx 1 root root 104193 May  1  2011 161901.pdf
-rwxrwxrwx 1 root root 103380 May  1  2011 161902.pdf
-rwxrwxrwx 1 root root 115664 May  1  2011 161903.pdf
-rwxrwxrwx 1 root root  88953 May  1  2011 161904.pdf
-rwxrwxrwx 1 root root 179268 May  1  2011 161905.pdf
-rwxrwxrwx 1 root root 116158 May 24  2011 161906.pdf
-rwxrwxrwx 1 root root 106033 May  1  2011 161907.pdf

換句話說,每個目錄都有16190{1..7}.pdf


現在假設我想將所有(從提到的所有目錄)移動161901.pdf到特定目錄(比如xyz),並重命名為它的父文件夾的 name.pdf。

解釋 :-

這是所有列表161901.pdf

$ find -name 161901.pdf
./May-June-2011/161901.pdf
./Nov-Dec-2011/161901.pdf
./Summer-2012/161901.pdf
./Summer-2013/161901.pdf
./Summer-2014/161901.pdf
./Winter-2012/161901.pdf
./Winter-2013/161901.pdf
./Winter-2014/161901.pdf

我希望應該使用新名稱(文件所在目錄的名稱)./May-June-2011/161901.pdf將其移入。即移動到xyz``May-June-2011.pdf``./May-June-2011/161901.pdf``./xyz/May-June-2011.pdf

./Nov-Dec-2011/161901.pdf./xyz/Nov-Dec-2011.pdf./Summer-2012/161901.pdfto等類似./xyz/Summer-2012.pdf(直到./Winter-2014/161901.pdf./xyz/Winter-2014.pdf

的預期輸出ls xyz是:

$ls xyz
May-June-2011.pdf
Nov-Dec-2011.pdf
Summer-2012.pdf
Summer-2013.pdf
Summer-2014.pdf
Winter-2012.pdf
Winter-2013.pdf
Winter-2014.pdf

我怎樣才能做到這一點?(如何find -exec或使用循環或其他東西)

Perl 模組Unicode::Tussle帶有一個非常有用的名為renamerename(1)的腳本(很不幸,因為該名稱與Linux上的標準衝突)。有了它,你可以做這樣的事情:

mkdir xyz
find . -name '*.pdf' -print0 | \
   rename -0 's!^\.!xyz!;  s!/[^/]*\.pdf$!.pdf!'

如果沒有 Perl,你仍然可以通過一些 shell 管道來做同樣的事情:

mkdir xyz
find . -name '*.pdf' | sed 's/^/mv /' >src
find . -name '*.pdf' | sed 's!^\./!xyz/!; s!/[^/]*\.pdf$!.pdf!' >dest
join src dest | sh -
rm -f src dest

而且,我相信其他人會很快指出,您甚至可以使用<(...)流程替換將其放在一行上。我不確定這會讓事情變得更清晰。如今的電腦已經足夠強大,可以使用更冗長的語法。;)

find當您不需要遞歸遍歷目錄樹時,它很少有用。這裡一個簡單的循環和 shell 萬用字元就足夠了。

for x in */161901.pdf; do
 mv -- "$x" "xyz/${x%/*}.pdf"
done

rename或者,在 Debian、Ubuntu 和衍生產品上使用基於 Perl 的命令(prename在 Arch 上,而不是rename其他發行版上的 Linux 命令):

rename 's!/.*!!; $_="xyz/$_.pdf"' */161901.pdf

或者,使用 zsh:

autoload -U zmv
zmv '(*)/161901.pdf' 'xyz/$1.pdf'

引用自:https://unix.stackexchange.com/questions/199301