回答:
ファイルの削除方法を尋ねる質問には細心の注意を払う必要があることを理解しています。私の最初の答えは速すぎたので、ファイルリストが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はファイルを保存せず、すべて削除されます。
ls
ディレクトリファイル名を提供し、egrep -vf filelist
50個のファイル名をフィルタリングします。すべてのファイルを削除したようです。
の引数を事前に作成します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"
'
)を追加する必要がkeep=( -name \'"$REPLY"\' )
ありkeep+=( -o -name \'"$REPLY"\' )
ます。
とzsh
:
mylist=(${(f)"$(<filelist)"})
print -rl -- *(.^e_'(($mylist[(Ie)$REPLY]))'_)
これは、行読み込み、filelist
配列内をしてから使用していますグロブ修飾子/ e
文字列を配列に存在しないファイル名だけを選択/グロブする:.
のみを選択し、通常のファイル(追加D
あなたのリストには、ドットファイルが含まれている場合)と否定^e_'expression'_
だけ、さらに選択したもののためにつまり、式がfalseを返します。つまり、名前($REPLY
)が配列の要素でない場合です。
あなたは結果に満足している場合は交換するprint -rl
とrm
、実際にファイルを削除するには:
rm -- *(.^e_'(($mylist[(Ie)$REPLY]))'_)
ファイルを再帰的に選択して削除するには、グロブ修飾子*/**
付きの${REPLY:t}
グロブを使用します。
rm -- */**(.^e_'(($mylist[(Ie)${REPLY:t}]))'_)
ディレクトリの内容を次のようにファイルに入れると、
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
以下のスクリプトを実行します。
all_files
。not_to_be_deleted_files
)。not_to_be_deleted_files
を
files_to_be_deleted
最後に追加していnot_to_be_deleted_files
ます。join
コマンドを使用して削除する必要があるファイルを見つけて
、出力をfiles_to_be_deleted
ファイルにリダイレクトしています。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
最初のディレクトリ、次に元のディレクトリ内のファイルを削除します。
リストに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ファイルの場合、数秒しかかかりませんでした。
安全でシンプル。
cd
ディレクトリに。
一時ディレクトリを作成します。
mv *.yourExlusionSelector.* ./temp
rm *
mv ./temp ./
rm -rf ./temp
完了しました。