名前がファイルリストの行と一致しないディレクトリ内のすべてのファイルを削除します


9

1000以上のファイルがあるディレクトリがあります。テキストファイルには、1行に1つずつ、約50個のファイル名があります。ファイル名がリストのエントリに対応していないディレクトリ内のすべてのファイルを削除したいのですが。これを行う最良の方法は何ですか?シェルスクリプトを開始しましたが、ファイル名がリストにあるかどうかを判別する適切なコマンドを判別できませんでした。ありがとう。

回答:


8

ファイルの削除方法を尋ねる質問には細心の注意を払う必要があることを理解しています。私の最初の答えは速すぎたので、ファイルリストがegrepで使用するために不正な形式である可能性があるという事実を理解しませんでした。私はそのリスクを減らすために答えを編集しました。

名前にスペースが含まれていないファイルでも機能するはずです。

まず正確なファイル名と一致するようにファイルリストを再構築します。

sed -e 's,^,^,' -e 's,$,$,'  filelist  > newfilelist 

rmコマンドをビルドする

cd your_directory
ls | egrep -vf newfilelist   | xargs -n 1 echo rm  >  rmscript

rmスクリプトが適切かどうかを確認します(「vim」または「less」で実行できます)。
次に、アクションを実行します。

sh -x rmscript

ファイルの名前にスペースが含まれている場合(ファイルに名前が含まれている場合、"これは機能しません):

ls | egrep -vf newfilelist  | sed 's,^\(.*\)$,rm "\1",' > rmscript

もちろん、ファイルリストは同じディレクトリにあってはいけません!

編集:

Nathanのファイルリストには、ディレクトリ内のすべてのファイルと一致する名前が含まれていました(「html」は「bob.html」と一致)。したがってegrep -vf、すべてのストリームを吸収したため、何も削除されませんでした。各ファイル名を「^」と「$」で囲むコマンドを追加しました。ネイサンのファイルリストが正しかったので、私は幸運でした。CR-LFで終了した行または追加のスペースを使用してDOS形式でフォーマットされている場合、egrepはファイルを保存せず、すべて削除されます。


previewコマンドを実行すると、「rm」が付いた1行が表示されます。実際のコマンドを実行すると、rmの引数が不足しているというエラーメッセージが表示されます。lsの結果を使用するには特別な構文が必要ですか?xargs入力のegrep?
ネイサン

@Nathan最初にディレクトリにcdする必要があります。特別な構文はありません。lsディレクトリファイル名を提供し、egrep -vf filelist50個のファイル名をフィルタリングします。すべてのファイルを削除したようです。
Emmanuel

@Emamanuel削除するファイルを含むディレクトリからコマンドを実行しています。
ネイサン

@Nathanはすべてのファイルを削除しますか?
Emmanuel

いいえ、まだ残っています。
ネイサン

1

の引数を事前に作成しますfind

{
  read -r
  keep=( -name "$REPLY" ) # no `-o` before the first one.
  while read -r; do
    keep+=( -o -name "$REPLY" )
  done
} < file_list.txt
find . -type f ! \( "${keep[@]}" \) -exec echo rm {} +

echoパーツを使用して、何が構築されるかを確認します。echo実際に実行するには、パーツを取り外してください。

更新:デモ:

##
# Demonstrate what files exist for testing.
# Show their whitespace:
~/foo $ printf '"%s"\n' *
" op"
" qr"
"abc"
"def"
"gh "
"ij "
"k l"
"keep"
"m n"

##
# Show the contents of the "keep" file,
# Including its whitespace:
~/foo $ cat -e keep
keep$
abc$
gh $
k l$
 op$

##
# Execute the script:
~/foo $ { read -r; keep=( -name "$REPLY" ); while read -r ; do keep+=( -o -name "$REPLY" ); done } < keep
~/foo $ find . -type f ! \( "${keep[@]}" \) -exec rm {} +

##
# Show what files remain:
~/foo $ printf '"%s"\n' *
" op"
"abc"
"gh "
"k l"
"keep"

私はこれが一番前のファイルリストを削除するので、これが一番好きです
eyoung100

私からの+1ですが、スペースはあまりうまく処理されません。おそらく、いくつかの単一引用符(')を追加する必要がkeep=( -name \'"$REPLY"\' )ありkeep+=( -o -name \'"$REPLY"\' )ます。
クリスティアンCiupitu 2014

誤ってファイルを削除してしまう可能性があるため、上記は危険です。
davidva 2014

@CristianCiupituでしょ?空白をうまく処理できることを示すデモを追加しました。
kojiro 2014

@davidvaどのような状況で?物事の削除を自動化するときはいつでも間違いを犯すリスクがありますが、質問のパラメーターの範囲内で、私のデモはこのアプローチが適切であることを証明していると思います。
kojiro 2014

1

zsh

mylist=(${(f)"$(<filelist)"})
print -rl -- *(.^e_'(($mylist[(Ie)$REPLY]))'_)

これは、行読み込み、filelist配列内をしてから使用していますグロブ修飾子/ e文字列を配列に存在しないファイル名だけを選択/グロブする:.のみを選択し、通常のファイル(追加Dあなたのリストには、ドットファイルが含まれている場合)と否定^e_'expression'_だけ、さらに選択したもののためにつまり、式がfalseを返します。つまり、名前($REPLYが配列の要素でない場合です。
あなたは結果に満足している場合は交換するprint -rlrm、実際にファイルを削除するには:

rm -- *(.^e_'(($mylist[(Ie)$REPLY]))'_)

ファイルを再帰的に選択して削除するには、グロブ修飾子*/**付きの${REPLY:t}グロブを使用します。

rm -- */**(.^e_'(($mylist[(Ie)${REPLY:t}]))'_)

0

ディレクトリの内容を次のようにファイルに入れると、

cd <somedirectory>
ls >> filelist

テキストエディタでファイルリストを開き、削除するファイル以外のすべてのファイルを削除します。上記の答えに対する反対のアプローチであるため、それは太字になっています

これを試して:

while read p || [[ -n $p ]]; 
echo $p
done < filelist

画面に出力されたファイルのリストが表示されたらrm -v、次のようにechoをに置き換えます。

while read p || [[ -n $p ]]; 
rm -v $p
done < filelist

0

以下のスクリプトを実行します。

  1. 最初は、ディレクトリ内に存在するすべてのファイルを検索し、出力を別のファイルに保存していますall_files
  2. 削除してはならないファイルのリストを含むファイルがあります(not_to_be_deleted_files)。
  3. これら2つのファイルが必要なため、ファイル名not_to_be_deleted_filesfiles_to_be_deleted最後に追加していnot_to_be_deleted_filesます。
  4. 今、私はlinux joinコマンドを使用して削除する必要があるファイルを見つけて 、出力をfiles_to_be_deleted ファイルにリダイレクトしています。
  5. ここで、最後のwhileループで、すべてのファイル名を読み取り、そのファイル名で files_to_be_deleted言及されているファイルを削除しています。

スクリプトは以下の通りです。

find /home/username/directory -type f | sed 's/.*\///' > all_files
echo all_files >> not_to_be_deleted_files
echo not_to_be_deleted_files >> not_to_be_deleted_files
echo files_to_be_deleted >> not_to_be_deleted_files
join -v 1 <(sort all_files_listed) <(sort files_not_to_be_deleted) >   files_to_be_deleted
while read file
rm  "$file"
done < files_to_be_deleted

PS:おそらく、これをスクリプトとして保存して実行したい場合は、を使用してスクリプト名を追加することもできますecho scriptname >> not_to_be_deleted_files

必須ではありませんが、後悔することはないのでやりたいです。小さなファイルセットをテストしたところ、私のシステムで動作しました。あなたが確認したい場合は、にしてみてくださいtest最初のディレクトリ、次に元のディレクトリ内のファイルを削除します。


0
  • リストをソースとして使用して、リスト内のすべてのファイルを新しい、新しい空のsave-dirに移動します。
  • リスト内のファイル数と保存されたファイル数を比較します。
  • 両方が一致する場合は、お気に入りの方法ですべての未保存のファイルを削除します。
  • 保存したファイルを元に戻します。

0

リストに18.000個のファイルがあったので、私はより安全ではるかに高速なアプローチを採用しました!大規模なDrupalインストールでイメージをクリーンアップする必要がありました。

リストにないファイルをすべて削除することは、リストにあるファイルのみを保持することと同じです。そのため、実際にリストから別の場所にファイルをコピーすることにしましたが、20 GBのファイルをコピーすると、スペースを取りすぎて非常に遅くなります。したがって、コツはhardlinks-lオプションを使用して、代わりにファイルをコピーすることですcp。これはほとんどスペースを取らず、非常に高速です。また、ディレクトリ構造を保持する必要があるため、この--parentsオプションを使用しました。

これは私のファイルリストからの抜粋です:

1px.png
misc/feed.png
modules/file/icons/x-office-presentation.png
modules/file/icons/x-office-spreadsheet.png
newsletter.png
sites/all/libraries/ckeditor/plugins/smiley/images/devil_smile.png
sites/all/libraries/ckeditor/plugins/smiley/images/regular_smile.png
sites/default/files/009313_PwC_banner_CBS_Observer_180x246px.jpg

したがって、例の行は、tempが目的地です:

cp -l --parents 'misc/feed.png' temp

これにより、次の構造が作成されます。

temp
  misc
    feed.png

ハードリンクが機能するには、宛先がソースと同じファイルシステムにある必要があることに注意してください。

次のステップは、スクリプトを作成することです。

sed -e "s,^,cp -l --parents '," -e "s,$,' /some/where/temp," filelist > newfilelist

ここで、空のディレクトリ/ some / where / tempがすでに作成されていると想定すると、次のようにファイルをコピーできます。

sh newfilelist 2> missing_files

エラーが最終的にどのように発生するかに注意してくださいmissing_files。このアプローチの追加ボーナスは、実際に存在しない元のリストからファイルのリストを取得できることです。

スクリプトの実行後、tempにはファイルリストにあるファイルのみが含まれますが、何も削除せず、追加のスペースを占有しません。結果に満足したら、サブフォルダーを含むすべての元のファイルを削除できます。

最後に、ファイルとフォルダを一時ファイルから元の場所に戻します。

18.000ファイルの場合、数秒しかかかりませんでした。


0

安全でシンプル。

cd ディレクトリに。

一時ディレクトリを作成します。

mv *.yourExlusionSelector.* ./temp
rm *
mv ./temp ./
rm -rf ./temp

完了しました。


サイトへようこそ。OPによって言及されたリストの名前が単純なパターンマッチングの結果である場合、アプローチは機能しますが、それは非常によくあることです-OPは除外するファイル名が特定のファイルに保存されると述べていることに注意してください。1つの静的パターンに頼るのではなく、そのファイルから除外パターンを読み取るように、または潜在的に複数のパターンをコンソールにタイプコピーする必要があるように、回答を拡張することができます。
AdminBee
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.