
給定許多包含許多不同檔案類型(csv、txt、jpg等)的目錄/子目錄,什麼命令將遞歸搜尋每個目錄並將檔案複製到以每個副檔名命名的新頂級目錄中。
有沒有辦法用一行程式碼來實現這一點?
答案1
解決方案
以下命令將列出目前目錄 ( .
) 中的所有文件,並將它們移至以其副檔名命名的目錄中./OUTPUT
:
for file in $(find . -type f) ; do EXTENSION=$(echo "$file" |sed 's/.*\.//g') ; rsync -av $file ./OUTPUT/$EXTENSION/ ; done
在運行上述命令之前,您需要:
- 在目前目錄中建立目錄 OUTPUT (
mkdir OUTPUT
) - 確保任何子目錄中沒有名稱匹配的文件
解釋
首先,循環將file
.txt 輸出中的檔案指派給變數find . -type f
。該命令的範例輸出find
如下:
./a/myfile1.zip
./a/b/adoc1.txt
./a/b/adoc2.txt
./a/b/adoc3.txt
./a/b/adoc4.txt
./a/myfile3.zip
./a/myfile4.zip
./a/myfile2.zip
該變數EXTENSION
已創建,其值是file
刪除了最後一個句號之前的所有內容的變數。那就./a/myfile1.zip
變成zip
。
然後,該檔案將同步(詳細程度為)到以檔案副檔名命名的v
目錄中。OUTPUT
在某些測試中運行此命令後我的文件樹的範例:
./a
./a/b
./a/b/adoc1.txt
./a/b/adoc2.txt
./a/b/adoc3.txt
./a/b/adoc4.txt
./a/b/c
./a/myfile1.zip
./a/myfile2.zip
./a/myfile3.zip
./a/myfile4.zip
./b
./b/c
./b/c/d
./b/c/file1.txt
./b/c/file2.txt
./b/c/file3.txt
./b/c/file4.txt
./c
./c/d
./c/d/e
./c/d/e/afile1.rar
./c/d/e/afile2.rar
./c/d/e/afile3.rar
./c/d/e/afile4.rar
./OUTPUT
./OUTPUT/rar
./OUTPUT/rar/afile1.rar
./OUTPUT/rar/afile2.rar
./OUTPUT/rar/afile3.rar
./OUTPUT/rar/afile4.rar
./OUTPUT/txt
./OUTPUT/txt/adoc1.txt
./OUTPUT/txt/adoc2.txt
./OUTPUT/txt/adoc3.txt
./OUTPUT/txt/adoc4.txt
./OUTPUT/txt/file1.txt
./OUTPUT/txt/file2.txt
./OUTPUT/txt/file3.txt
./OUTPUT/txt/file4.txt
./OUTPUT/zip
./OUTPUT/zip/myfile1.zip
./OUTPUT/zip/myfile2.zip
./OUTPUT/zip/myfile3.zip
./OUTPUT/zip/myfile4.zip
答案2
這可以非常簡單地完成尋找,正如亞歷克斯正確建議的那樣:假設要掃描文件的目錄是/path1/to/some/dir,並且您希望將文件移至/path2/to/other/dir/txt等等,
find /path1/some/dir -type f -exec bash -c 'MYDIR=/path2/to/other/dir${0##*.}; [ -d $MYDIR ] && mv $0 $MYDIR || mv $0 /path3/to/miscellanea' {} \;
該指令首先查找所有文件(-f型) 包含在目錄中/path1/to/some/dir及其所有子目錄,然後傳遞每個此類檔案的名稱({})到一個小的 bash 兩行程式碼,它首先從檔案名稱中提取副檔名(稱為$0在 bash 中)並將其指派給本地 shell 變數MYDIR, 然後測試是否存在合適的目錄(如果沒有這樣的目錄,那麼可能我們犯了一個錯誤),以及該目錄是否存在(&& ...)它將文件移動到適當的目錄中,否則(||...)它將文件放置在預設位置,/path3/to/雜項。
上面假設您已經建立了必要的目錄,/path2/to/other/dir/txt等等。如果您想隨時隨地創建它們,則必須將上面的內容修改為:
find /path1/some/dir -type f -exec bash -c 'MYDIR=/path2/to/other/dir/${0##*.}; mkdir -p $MYDIR && mv $0 $MYDIR' {} \;