![識別兩個不同目錄之間的公共子目錄名稱並將其刪除](https://rvso.com/image/97237/%E8%AD%98%E5%88%A5%E5%85%A9%E5%80%8B%E4%B8%8D%E5%90%8C%E7%9B%AE%E9%8C%84%E4%B9%8B%E9%96%93%E7%9A%84%E5%85%AC%E5%85%B1%E5%AD%90%E7%9B%AE%E9%8C%84%E5%90%8D%E7%A8%B1%E4%B8%A6%E5%B0%87%E5%85%B6%E5%88%AA%E9%99%A4.png)
我有兩個目錄dir1
,dir2
其中有數百個子目錄depth 1
。我只需要dir1
和之間共有的子目錄名稱的信息,dir2
然後系統地從 中刪除它們dir2
。我不需要比較文件或文件內容。表演
diff -qr dir_one dir_two | sort
也產生檔名,我目前對此不感興趣。
答案1
對於您的用例,您可以避免確認公共目錄,因為rm -rf
只是忽略不存在的目錄。
所以這就足夠了find
全部目錄dir1
並從中刪除它們 dir2
:
find dir1 -mindepth 1 -maxdepth 1 -type d -printf "dir2/%f\0" |xargs -0 rm -rf --
一些解釋。預設find
會列印所有目錄,其完整路徑為dir1
.因此,我們-printf
只列印檔案名,不含前導目錄 (%f) 以及我們要刪除的其他路徑「dir2」。此外,我們使用空字節“\0”而不是換行符來終止字串,以使用xarg
選項-0
,這使得所有這些對於帶有空格的檔案名稱都是安全的。然後xargs
將讀取標準輸入並rm
透過添加所有字串作為參數來執行命令。
echo
請注意,在實際刪除它們之前,您可以透過新增僅列印命令來測試命令列rm
:
find dir1 -mindepth 1 -maxdepth 1 -type d -printf "dir2/%f\0" |xargs -0 echo rm -rf --
至僅清單您可以使用的常用目錄ls
來取代rm
(新增 2>/dev/null 以忽略不存在的目錄):
find dir1 -mindepth 1 -maxdepth 1 -type d -printf "dir2/%f\0" |xargs -0 -r ls -d -- 2>/dev/null
答案2
comm -1 -3 <( cd dir1 && find -maxdepth 1 -type d | sort ) <( cd dir2 && find -maxdepth 1 -type d | sort ) | ( cd dir2 && xargs rm -rf )
為了方便閱讀,使用換行符:
comm -1 -3 <( cd dir1 && find -maxdepth 1 -type d | sort ) \
<( cd dir2 && find -maxdepth 1 -type d | sort ) \
| ( cd dir2 && xargs rm -rf )
解釋
find -maxdepth 1 -type d
僅列出沒有子目錄的目錄。
cd dir1 && find -maxdepth 1 -type d | sort
先更改目錄,然後列出目錄。
<( ... )
流程替代。
comm -1 -3 <( ... ) <( ... )
取得第一個輸入和第二個輸入,並列印第二個輸入特有的行。實際上,這將列印位於dir2
但不在 中的目錄dir1
。
... | ( cd dir2 && xargs rm -rf )
變更工作目錄,然後使用上一個指令的輸出作為參數dir2
執行。rm -rf
實際上,這將刪除位於dir2
但不在 中的目錄dir1
。
首先透過移除管道xargs
並檢查輸出來進行測試。
答案3
find dir1 dir2 -maxdepth 2 | egrep '/' | xargs --max-args 1 basename | sort | uniq -c | egrep -v '^ 1 ' | while read n de ; do echo rm -rfv dir2/$de ; done
正確時消除迴聲。