使用find尋找某個目錄並刪除其中除一個目錄外的所有文件

使用find尋找某個目錄並刪除其中除一個目錄外的所有文件

我遇到以下問題。我有一個目錄結構,想要刪除名為 的目錄中的所有內容Caches。除所有名為 的目錄外,所有內容都應刪除Snapshots。我不知道如何做到這一點尋找或我知道的任何其他命令。

我問的原因是:在 iOS 上,每個應用程式都有自己的 Caches 目錄。這些有時無法正確清除,具體取決於應用程式。有了這個答案的解決方案,當裝置的驅動器安裝在另一台電腦上時,例如使用 FUSE (iExplorer),人們將能夠清除 iOS 上的緩存,從而優化磁碟空間。

這是我到目前為止所擁有的:

find . 2>/dev/null -type d -name "Caches" -maxdepth 3 -print

這會傳回類似以下內容的內容:

./Library/Caches

當我執行 a 時,ls ./Library/Caches我會看到所有內容和Snapshots目錄,我想排除它們,因為最終我想要-delete除此之外的所有內容。


我想要這樣的東西:

  Before:                            After:

  .                                  .
  ├── a                              ├── a
  │   ├── a                          │   ├── a
  │   └── Caches                     │   └── Caches
  │       ├── a                      │       └── a
  │       │   └── Snapshots          │           └── Snapshots
  │       │       └── a              │               └── a
  │       ├── b                      └── b
  │       │   └── a                      └── c
  │       └── c                  
  └── b
      ├── c
      └── Caches
          ├── a
          │   └── foo
          │       └── a
          └── b
              └── a

答案1

我對問題的措辭有點困惑。如果您想要刪除目錄中./Library/Caches除名為 的單一資料夾之外的所有內容Snapshots,則無需使用find.在 中bash,shell glob 是最簡單的方法:

shopt -s extglob  # probably already enabled
echo Library/Caches/!(Snapshots)

如果這會列印您要刪除的所有檔案/目錄,則替換echorm -f --.

如果您想要保留Snapshots下面的目錄樹的不同層級的多個目錄,那麼使用 GNU您可以執行以下操作:./Library/Cachesfind

find Library/Caches ! -path '*Snapshots*'

這應該列印所有文件/目錄,不包括Snapshots 路徑中的文件/目錄。它將包含包含目錄(或其子目錄包含)的目錄Snapshots,但find ... -delete不會刪除這些目錄,而是列印錯誤,指出它們不為空。一旦你感到高興,就添加-delete到最後。

需要注意的是,這將留下任何文件命名Snapshots完好。如果這是一個問題,請改為:

find Library/Caches \( ! -path '*Snapshots*' -o -type f -name Snapshots \)

高興的時候再補充-delete

答案2

find . -depth -print0 | perl -0lne '
  if ("$_/" =~ m{/Caches(/.*)}s && $1 !~ m{/Snapshots/}) {rmdir $_ or unlink $_}'

如果你find不支持-print0,你可以用 取代它-exec printf '%s\0' {} +

這個想法是列印以 NUL 結尾的檔案清單(因為 0 是唯一不能出現在檔案路徑中的位元組),並使用perl's-n-0選項為每個檔案名稱運行一些程式碼($_設定為檔案名稱) )。

使用 時-depth,檔案將在其父目錄之前列印。如果檔案或目錄depth的路徑/Caches/後面不包含/Snapshosts/.

答案3

我不是find巫師,所以我不想說你不能用 來做到這一點find,但我確實知道可以用幾行 來完成bash。鑑於我正確理解您的目錄結構:

#!/bin/bash

for i in Library/Caches/*; do
    if [[ -d "$i" ]]; then
         [[ "$i" =~ "Snapshots" ]] ||  echo "rm-ing  $i" # change to rm -rf "$i" to use
    fi
done

for語句傳回 中的每個項目Library/Caches/。該if [[ -d "$i" ]]語句檢查每個項目是否為目錄,如果是,請檢查它的名稱以查看它是否包含“Snapshots” [[ "$i" =~ "Snapshots" ]]。因為沒有運算符可以否定正規表示式匹配,例如!=~,所以我過去常常在上一個命令不成功時||執行rm,例如目錄名稱不包含快照。

這將在任何使用的現代系統上運行bash,但它必須有bash。另外,您可能需要嘗試目錄結構,但這應該適合您。

答案4

第一部分:找到名為caches的目錄並對它們執行一些操作

find . -name Caches -type d -exec … \;

第二部分:遍歷快取目錄,並刪除所有內容,但保留Snapshots子目錄及其內容(以及通往它們的路徑)。進行深度優先遍歷,這樣目錄一旦變空就可以刪除。

    find /path/to/Caches -depth -name Snapshots -type d -prune \
                             -o \( -type d -empty -o ! -type d \) -delete

現在將它們組合在一起。

find . -name Caches -type d -exec
    find {} -depth -name Snapshots -type d -prune \
                -o \( -type d -empty -o ! -type d \) -delete

相關內容