ディレクトリから一部を除くすべてのファイルを削除します


215

を使用している場合sudo rm -r、次の例外を除いて、すべてのファイルを削除するにはどうすればよいですか。

textfile.txt
backup.tar.gz
script.php
database.sql
info.txt


1
この質問を読むには2つの方法があり、既存の回答は両方の解釈をカバーしています:どちらか:(a)指定された名前のファイルをターゲットディレクトリに直接保存し、- rm -r暗黙的に- サブディレクトリを含む他のすべてを削除します -それらが含まれている場合でも指定された名前のファイル。または:(b)ターゲットディレクトリのサブツリー全体をトラバースし、各ディレクトリで、リストされている名前のファイルを除くすべてのファイルを削除します。
mklement0 2014年

回答:


219
find [path] -type f -not -name 'textfile.txt' -not -name 'backup.tar.gz' -delete

-type ffindを指定しない場合、ディレクトリも一覧表示されます。


または、非常に便利な組み合わせを使用したより一般的なソリューションfind | xargs

find [path] -type f -not -name 'EXPR' -print0 | xargs -0 rm --

たとえば、現在のディレクトリ内のすべての非txtファイルを削除します。

find . -type f -not -name '*txt' -print0 | xargs -0 rm --

print0および-0削除すべきファイル名のいずれかにスペースがある場合の組み合わせが必要とされています。


2
xargsにはテキストサイズの制限があるようです
frazras 2013

26
複数のパターンを削除するには:find . -type f -not -name '*ignore1' -not -name '*ignore2' | xargs rm
Siwei Shen申思维

5
ディレクトリはどうですか?すべてのファイルが削除されますが、フォルダは削除されますか?!
orezvani 2013

31
「| xargs rm」の代わりに、findは-deleteパラメーターを取ります。
EmilStenström2013

1
-print0 | xargs -0 rm --あなたの代わりにできること-delete
Andy

150
rm !(textfile.txt|backup.tar.gz|script.php|database.sql|info.txt)

extglob(拡張パターンマッチング)をBASHで有効にする必要があります(有効になっていない場合)。

shopt -s extglob

2
予期しないトークン `( 'の近くで構文エラーが発生しますshopt -s extglob; rm -rf !(README|LICENSE)。理由は何ですか?
Dennis

@nic覚えていません、すみません。たぶんオプションで使っfindてしまい-deleteました。
Dennis

これは私にとって最良のソリューションであり、私のUbuntu 12.04.4 LTSでデフォルトで動作します。shoptは必要ありません
xtian

3
@nic、@Dennis:構文エラー以外のその何か示唆bashを使用した、例えば、dashextglobサポートされていません。ただし、対話型 bashシェルでは、さまざまな理由がありますが、コマンドは前述のように機能しません。それの不足:shopt -s extglobBY ITSELFを実行します。shopt extglob正常に有効になったら(で確認)、を実行しrm -rf !(README|LICENSE)ます。(extglobまだ有効になっていませんが、コマンドが実行される前に履歴展開!(...)によって評価されます。これは失敗する可能性が高いため、NEITHERコマンドが実行され、決してオンになりません。)extglob
mklement0

2
@ nic、@ Dennis、@ mklement0:.shファイル(#!/ bin / bash)内でコマンドを実行すると、「予期しないトークンに近い構文エラー()」と同じ問題が発生しましたが、コマンドで実行しているときは発生しませんでしたラインインターフェイスそれは他にいることが判明した。shopt -s extglobコマンドラインインタフェースで実行すると、私は私のスクリプトファイル内でそれを再実行する必要がありました。これは私のために問題を解決した。。
Ahresse

41

find . | grep -v "excluded files criteria" | xargs rm

これにより、現在のディレクトリ内のすべてのファイルが一覧表示され、次に条件に一致しないすべてのファイルが一覧表示され(ディレクトリ名と一致することに注意)、それらを削除します。

更新:編集に基づいて、リストしたファイル以外のすべてを現在のディレクトリから本当に削除したい場合は、これを使用できます:

mkdir /tmp_backup && mv textfile.txt backup.tar.gz script.php database.sql info.txt /tmp_backup/ && rm -r && mv /tmp_backup/* . && rmdir /tmp_backup

バックアップディレクトリを作成し/tmp_backup(root権限を持っていますよね?)、リストしたファイルをそのディレクトリに移動し、現在のディレクトリ内のすべてを再帰的に削除します(あなたが正しいディレクトリにいることを知っていますよね?)現在のディレクトリに戻って/tmp_backup、最後にすべてを削除し/tmp_backupます。

ルートからバックアップディレクトリを選択しました。ルートからすべてを再帰的に削除しようとすると、システムに大きな問題が発生するからです。

確かにこれを行うにはよりエレガントな方法がありますが、これはかなり簡単です。


2
egrepでも非常にうまく機能します。たとえば、中間のラテックスファイルをクリーニングする場合:find . | egrep -v "\.tex|\.bib" | xargs rm
mtsz

素晴らしいコマンド!ディレクトリを削除するには、rm -rに変更します
Aris

1
除外された基準以外の現在のディレクトリのすべてを単に削除したい場合:find . -maxdepth 1 | grep -v "exclude these" | xargs rm -r不必要にディレクトリにドリルダウンする必要がないため、はるかに高速に動作します。
ビリーノア2014年

findパイプライン:脇効率の問題(3つのコマンドは何のために使用されているfindのみで行うことができます)、これは仕事埋め込みスペースを含むファイル名を対象としており、潜在的に間違ったファイルを削除しますとしません。
mklement0 2014年

「保存される」ファイルを別の場所(/tmp_backup)に保存するコマンドは、中断された場合、正常に終了しません。ユーザーの観点から見ると、ファイルを探すためにどこに行くかわからない限り、すべてのファイルが消えています。 。そのため、私はこのタイプの戦略には賛成しません。
Craig McQueen


19

BashでGLOBIGNORE環境変数を使用できます。

phpとsql以外のすべてのファイルを削除したい場合は、次のようにします-

export GLOBIGNORE=*.php:*.sql
rm *
export GLOBIGNORE=

このようにGLOBIGNOREを設定すると、「ls *」や「rm *」のように使用されるワイルドカードのphpとsqlが無視されます。したがって、変数の設定後に「rm *」を使用すると、txtファイルとtar.gzファイルのみが削除されます。


6
+1; 設定と復元にシンプルな代替GLOBIGNORE変数がサブシェルを使用することです:(GLOBIGNORE='*.php:*.sql'; rm *)
mklement0

19

私はサブクエリリストを使用することを好みます:

rm -r `ls | grep -v "textfile.txt\|backup.tar.gz\|script.php\|database.sql\|info.txt"`

-v、--invert-match一致しない行を選択します

\| セパレーター


1
エレガントなソリューション
Joshua Salazar

9

誰もそれを言わなかったので:

  • 削除したくないファイルを安全な場所にコピーします
  • すべてのファイルを削除する
  • コピーしたファイルを元の場所に戻す

2
アクセス許可をコピーして戻した後は、アクセス許可を処理する必要があるため、より複雑になります。
Romulus 2014年

2
@RemusAvram cpまたはで適切なスイッチを使用rsyncして、権限を保持できます。とにかく、これはOPへの回答としてここにその位置を持っている(提案として与えられた)代替方法にすぎません。
gniourf_gniourf 2014年

これは、保持されるファイルが他のプロセスによってアクティブに使用されている多くの状況では適切でない場合があります。また、削除するファイルがごく一部であり、多数のファイルが関係しているのも面倒です。
codeforester

@codeforester:確かに。しかし、それが適切である状況もあります...実際、私はあなたのコメントの要点を実際には見ていません:)
gniourf_gniourf

6

このためのforループを記述できます...%)

for x in *
do
        if [ "$x" != "exclude_criteria" ]
        then
                rm -f $x;
        fi
done;

6

OPには少し遅れますが、後でGoogleでここに到着するすべての人に役立つと思います...

@awiの回答と、@ Jamie Bullockの-deleteに関するコメントが本当に役に立ちました。最小限の入力で毎回異なるファイル名/タイプを無視して異なるディレクトリでこれを行うことができる単純なユーティリティ:

rm_except(または名前を付けたいもの)

#!/bin/bash

ignore=""

for fignore in "$@"; do
  ignore=${ignore}"-not -name ${fignore} "
done

find . -type f $ignore -delete

たとえば、テキストファイルとfoo.bar以外のすべてを削除するには、次のようにします。

rm_except *.txt foo.bar 

@mishunikaに似ていますが、if句がありません。


5

あなたが使用しzshている場合、私は強くお勧めします。

rm -rf ^file/folder pattern to avoid

extended_glob

setopt extended_glob
rm -- ^*.txt
rm -- ^*.(sql|txt)

4

それを試してみました:

rm -r !(Applications|"Virtualbox VMs"|Downloads|Documents|Desktop|Public)

しかし、スペースを含む名前は(いつものように)難しいです。Virtualbox\ VMs代わりに引用符も試してみました。常にそのディレクトリ(Virtualbox VMs)を削除します。


ファイルに対しては機能しません。rm !(myfile.txt)を含むすべてを削除myfile.txt
khaverim '10

shopt -s extglob@ pl1nkが指摘したように、最初に実行する必要があります
zhuguowei 2017年

はい、bashで拡張グロビングextglob)をアクティブにすることは非常に重要です。ラボで数台のMacを使用して、日常的にこれを行っています。 shopt -s extglobそしてcd /Users/alumno/、最後にrm -rf !(Applications|Virtualbox*VMs|Downloads|Documents|Desktop|Public|Library) 、拡張
グロビング

4

ただ:

rm $(ls -I "*.txt" ) #Deletes file type except *.txt

または:

rm $(ls -I "*.txt" -I "*.pdf" ) #Deletes file types except *.txt & *.pdf

これは推奨されません。ls出力の解析が問題になる可能性があります。詳細はこちらをご覧ください。
RJ

2

ファイルを不変にします。rootでさえ、それらを削除することはできません。

chattr +i textfile.txt backup.tar.gz script.php database.sql info.txt
rm *

他のすべてのファイルは削除されました。
最終的には変更可能にリセットできます。

chattr -i *

0

これは@ siwei-shenからのコメントに似ていますが、-o複数のパターンを実行するにはフラグが必要です。-oフラグが「または」の略

find . -type f -not -name '*ignore1' -o -not -name '*ignore2' | xargs rm


0

これは、2つのコマンドシーケンスで実行できます。最初に、除外したくないファイルの名前で配列を定義します。

files=( backup.tar.gz script.php database.sql info.txt )

その後、除外するディレクトリ内のすべてのファイルをループし、除外したくない配列にファイル名があるかどうかを確認します。そうでない場合は、ファイルを削除します。

for file in *; do
  if [[ ! " ${files[@]} " ~= "$file"  ]];then
    rm "$file"
  fi
done

正規表現の比較は正しくありません。保護されたファイルの1つの部分文字列である名前のファイルは保持されます(周囲のスペースはそれを多少軽減しますが、ファイル名にはスペースを含めることができます)。すべてのファイルの配列を収集し、その配列から除外するファイルを差し引き、残りのファイルを削除する必要があります。
tripleee

-1

まだ誰もこれについて言及していないので、ある特定のケースでは:

OLD_FILES=`echo *`
... create new files ...
rm -r $OLD_FILES

(または単にrm $OLD_FILES

または

OLD_FILES=`ls *`
... create new files ...
rm -r $OLD_FILES

shopt -s nullglob一部のファイルが存在する場合と存在しない場合は、次のように使用する必要があります。

SET_OLD_NULLGLOB=`shopt -p nullglob`
shopt -s nullglob
FILES=`echo *.sh *.bash`
$SET_OLD_NULLGLOB

nullglob echo *.sh *.bashがない場合、「a.sh b.sh * .bash」が表示される場合があります。

(OSXで機能しない場合でも、私はこの答えを好みます


Leonardo Hermosoによる既存の回答では、これはバグが少なくなっています。これは、スペースを含むファイル名では失敗します。配列を使用すると、その特定の問題がエレガントに解決されます(また、プライベート変数に大文字を使用することはそれほど避けられませんが、これは一般に回避されます)。
tripleee

-3

直接コマンドを実行するのではなく、必要なファイルを現在のディレクトリの外の一時ディレクトリに移動してください。次に、rm *またはを使用してすべてのファイルを削除しますrm -r *

次に、必要なファイルを現在のディレクトリに移動します。


これは、保持されるファイルが他のプロセスによってアクティブに使用されている多くの状況では適切でない場合があります。また、削除するファイルがごく一部であり、多数のファイルが関係しているのも面倒です。
codeforester

-3

file.nameを除くすべてを削除します。

ls -d /path/to/your/files/* |grep -v file.name|xargs rm -rf

2
これはひどく失敗し、ディレクトリやファイルにスペースや異常な文字が含まれていると、データが失われる可能性があります。lsを解析してはいけません。mywiki.wooledge.org/ParsingLs
RJ
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.