Unix-パターンを除くファイルとフォルダを削除します


10

最近、特定のパターンに一致するものを除いて、ディレクトリ内のすべてのファイル/フォルダーを削除するタスクに直面しました。だから私は仕事をするために一行のunixコマンドを作り上げました。1行だけにする必要がありますか?私はそうではないと思いますが、それは間違いなくそのように涼しいです!

問題はかなり単純ですが、結局のところ、私のソリューションがどれほど複雑になっているかに少し驚いていました。これが私が使ったコマンドです。注:改行文字を含むファイル名を処理しないため、これは不適切なソリューションです(私の状況では問題ではありませんでした)。

ls | grep -v PATTERN | xargs -n1 -IREPLACE rm -rf REPLACE

PATTERNに一致するフォルダに再帰的に戻りたくないため、「find」コマンドを使用しませんでした。たとえば、次のファイル構造を考えます。

file_foo.txt
first_dir
  |
  +--> contents
  +--> ...
foo_dir
  |
  +--> anotherfile.txt
  +--> morefiles.log
foo_file.txt
somefile.txt

パターン "foo"を使用すると、 "first_dir"(もちろんその内容)と "somefile.txt"("anotherfile.txt"や "morefiles.log"ではない)のみが削除されます。

質問、これを達成するためのより優れた(よりエレガントで正しい)方法はありますか?


編集:
最近、「検索」がより良いオプションである可能性があることに私の注意が向けられました:

find * -maxdepth 0 ! -name PATTERN -print0 | xargs -0n1 rm -rf

このソリューションは、改行文字を含むパスを正しく処理します。


編集:誤った「the_dir」を「first_dir」に修正しました。
joxl

回答:


10

次の例にはecho、実際に使用する前にパターンをテストできるように接頭辞が付いています。を削除してechoをアクティブにしrm -rfます。rm -ri確認のためプロンプトを表示する代わりに。

kshには、そのグロビングに対して否定的な一致拡張があります。

# ksh
echo rm -rf !(*foo*)

オプションを設定すると、同じ構文がbashで使用できextglobます。

# bash
shopt -s extglob
echo rm -rf !(*foo*)

zshにはこのための独自の構文があります。

# zsh
setopt extended_glob
echo rm -rf ^*foo*

また、kshスタイルの構文を使用することもできます。

# zsh: ksh-style glob syntax
setopt ksh_glob no_bare_glob_qual
echo rm -rf !(*foo*)

# zsh: ksh-style glob syntax, adapted for the default bare_glob_qual option
setopt ksh_glob bare_glob_qual
echo rm -rf (!(*foo*))

シンプルでエレガント、改行文字、(ほぼ)1行を処理します(shopt -s extglob.bashrcファイルに追加したため、現在 1行です)。パーフェクト!私の評判が許す限りすぐに賛成投票を約束します。
joxl

7

これが別のfind解決策です。これが実際のアドバンテージよりも優れているかどうかはわかりませんがxargs、必要ではなく、*があまりにも多くの名前に拡張されるというまれな可能性を考慮しています。

find . -maxdepth 1 ! -name PATTERN -type f -delete

また、-type fディレクトリを削除しようとしないように追加しました。

警告:-delete強力です。私は私のテストファイルの1つに0のアクセス許可を与え、上記のコマンドはためらうことなくそれを削除しました。


6
最初にテストします。に置き換え-delete-print、必要なファイルが見つかったかどうかを確認します。すべて問題なければ、コマンド履歴を使用して(たとえば、上ボタンを押して)前のコマンドに戻り、同じ検索フィルターで作業していることを確認します。
Doug Harris

注意深く読んでください。ディレクトリを削除たいのですが。また、find -delete空でないディレクトリは削除されません。find -maxdepth 1「。」に一致することにも注意してください。(現在のディレクトリ)これは本当に悪いです。私はを排除するというあなたの考えが好きですが、代わりにxargs使うかもしれませんfind -execfind * -maxdepth 0 ! -name PATTERN -exec rm -rf '{}' \;
joxl '27 / 07/27

0

代わりに、このrebolスクリプトの例http://askcodegeneration.com/keep-subversion/を使用できます。これは、より理解しやすく、フォルダーの選択や確認などのユーザー操作を管理できます。

delete-file: func[file][
    if/else none? find file "/.svn/" [
        delete file
    ][
        print ["keeping" file]
    ]
]
dir: request-dir
ans: ask rejoin ["Do you confirm " dir "? (Yes): "]
if (ans = "Yes") [
    foreach-file dir :delete-file
]
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.