
測試環境:
- 建立從
0
到 的目錄並用從到 的9
檔案填充它們a
z
$ mkdir {0..9} && touch {0..9}/{a..z}
- 的結果
find
:$ find -type f ./0/a ./0/b ... ./9/y ./9/z
如何轉換輸出,使其看起來像這樣:
./0a
./0b
...
./9y
./9z
答案1
使用 Perl 的獨立rename
指令:
rename -n 's|/||' */*
如果一切正常,請刪除-n
然後刪除剩餘的空目錄。
rmdir {0..9}
答案2
透過 POSIX 工具,
find . -type f -exec sh -c 'for f; do dirn="${f%/*}"; mv -- "$f" "$dirn${f##*/}"; done' sh {} +
find
呼叫 shell 並為每個檔案執行 for 循環。
dirn="${f%/*}"
透過排除(並包含)檔案名稱中最後一個斜槓之後的所有內容來取得父目錄名稱。${f##*/}
透過排除檔案名稱中最後一個斜線之前(並包含)的所有內容來取得不含路徑的檔案名稱。
這兩個 shell 結構的作用與dirname
和basename
,所以該指令的等效形式是
find . -type f -exec sh -c 'for f; do mv -- "$f" "$(dirname "$f")$(basename "$f")"; done' sh {} +
,儘管這個應該慢一些,因為它需要為每個檔案產生兩個額外的進程。
如果您不需要進入多個目錄(如您的範例所示),則可以使用一個簡單的 shell 循環來完成:
for f in */*; do dirn="${f%/*}"; echo mv -- "$f" "$dirn${f##*/}"; done