Unix:ファイルにリストされているファイルを削除する方法


92

削除したいファイルマスクのリストを含む長いテキストファイルがあります

例:

/tmp/aaa.jpg
/var/www1/*
/var/www/qwerty.php

それらを削除する必要があります。rm `cat 1.txt`を試しましたが、リストが長すぎると表示されます。

このコマンドが見つかりましたが、リストからフォルダーを確認すると、一部のフォルダーにはまだファイルがあります。 xargs rm <1.txt手動のrm呼び出しにより、そのようなフォルダーからファイルが削除されるため、アクセス許可に問題はありません。


8
6年後ですが、答えの1つを受け入れていただけませんか。これにより、質問が解決済みとしてマークされ、他のユーザーにも役立ちます。
MERose 2017年

回答:


114

これはあまり効率的ではありませんが、グロブパターンが必要な場合は機能します(/ var / www / *のように)

for f in $(cat 1.txt) ; do 
  rm "$f"
done

パターンがなく、ファイル内のパスに空白やその他の奇妙なものが含まれていないことが確実な場合は、次のようにxargsを使用できます。

xargs rm < 1.txt

4
パスにスペースが含まれている場合、最初のソリューション(CATを使用)はどうなりますか?
a.dibacco

58

ファイルのリストがファイル内にあると仮定して、次の手順を1.txt実行します。

xargs rm -r <1.txt

この-rオプションにより、で指定された任意のディレクトリに再帰が発生し1.txtます。

読み取り専用のファイルがある場合は、-fオプションを使用して強制的に削除します。

xargs rm -rf <1.txt

入力との注意が必要任意のプログラム的な削除を行いますツール。確認し、特定の入力ファイルで指定されたファイルが実際に削除されること。一見単純なタイプミスには特に注意してください。たとえば、ファイルとそのサフィックスの間にスペースを入力すると、2つの別々のファイル名のように見えます。

file .txt

実際には2つの別々のファイルです:file.txt

これはそれほど危険ではないように思われるかもしれませんが、タイプミスが次のようなものである場合:

myoldfiles *

次に、で始まるすべてのファイルを削除する代わりに、現在のディレクトリ内のすべての非ドットファイルとディレクトリをmyoldfiles削除することにmyoldfilesなります。おそらくあなたが望んでいたものではありません。


1
「myoldfiles /」または「/ tmp」は-rfでさらに悲惨です。「/」の横のスペース文字に注意してください。
レイ

23

これを使って:

while IFS= read -r file ; do rm -- "$file" ; done < delete.list

グロブ拡張が必要な​​場合は、引用を省略できます$file

IFS=""
while read -r file ; do rm -- $file ; done < delete.list

ただし、ファイル名には「問題のある」コンテンツが含まれている可能性があるため、引用符で囲まれていないバージョンを使用することに注意してください。ファイル内のこのパターンを想像してみてください

*
*/*
*/*/*

これにより、現在のディレクトリからかなりの量が削除されます。グロブパターンが不要になるように削除リストを準備してから、最初の例のように引用符使用することをお勧めします。


3
これは、現在、そのハンドルのすべての唯一の答えである/My Dir With Spaces/ /Spaces and globs/*.txt--file-with-leading-dashesとボーナスとして、それはPOSIXだとGNU / Linuxでは、MacOSのとBSDで動作します。
その他の男

17

'\ n'を使用して、改行文字を区切り文字として定義できます。

xargs -d '\n' rm < 1.txt

1.txtにスペースを含むパスが含まれていると、不要なものが削除される可能性があるため、-rfには注意してください。そのため、改行区切り文字は少し安全です。

BSDシステムでは、-0オプションを使用して、次のように改行文字を区切り文字として使用できます。

xargs -0 rm < 1.txt

1
OS Xでは、これは私をxargs: illegal option -- d
魅了し

いい視点ね。よりも、他のオプションはありませんようです-0OS X上で
レイ

2
xargs -I_ rm _
OSX

(なしがありますBSDのxargsのを使用している場合-d)には、最初にヌルに改行を変換することができます:tr '\n' '\0' < 1.txt | xargs -0 rm
OrangeDog

13

このワンライナーを使用できます:

cat 1.txt | xargs echo rm | sh

これはシェル拡張を行いますがrm、最小回数実行します。


拡張が長すぎない限り?
ダグラスリーダー2011

1
確かに、globは長すぎる引数リストを生成する可能性があります-各rmに渡される引数の数を減らすために-n <n>引数を追加できますが、xargsそれでも制限を超える単一のglobから保護することはできません。
tgdavies 2011

13

xargs -I{} sh -c 'rm {}' < 1.txtあなたがやりたいことをする必要があります。このコマンドには注意してください。そのファイルに誤ったエントリが1つあると、多くの問題が発生する可能性があります。

この回答は、@ tdaviesがオリジナルがシェル拡張を行わなかったことを指摘した後に編集されました。


ありがとう、しかしフォルダを削除する必要はありません、ファイルだけ
Alexander

2
シェルによって「見られる」ことはないため、グロブは拡張されません。
tgdavies 2011

@tdaviesすごい-その通りです。このコマンドは(少し醜いですが)機能します:xargs -I{} sh -c 'rm {}' < 1.txt
Mark Drago

4

この特定のケースでは、他の回答で引用されている危険性のために、私は

  1. たとえば、Vimと:%s/\s/\\\0/gで編集し、すべてのスペース文字をバックスラッシュでエスケープします。

  2. 次に:%s/^/rm -rf /、コマンドの前に。では-r、あなたのファイルは、その中に含まれる後にリストされているディレクトリを持つように心配する必要はありません、として-f、それが見つからないファイルや重複したエントリに文句を言うことはありません。

  3. すべてのコマンドを実行します。 $ source 1.txt


エスケープが必要な文字はスペースだけではありません。ファイル名でよく使用されるのは、不要な展開につながる可能性のあるあらゆる種類の角かっこです。
emk22 0319年

4

cat 1.txt | xargs rm -f | bash コマンドを実行すると、ファイルに対してのみ次のことが実行されます。

cat 1.txt | xargs rm -rf | bash コマンドを実行すると、次の再帰的な動作が実行されます。


2

別の方法を提供するために、次のコマンドを使用することもできます

$ cat to_remove
/tmp/file1
/tmp/file2
/tmp/file3
$ rm $( cat to_remove )

1

別のループの例を次に示します。これには、エントリが「ファイル」(または「ディレクトリ」など)であるかどうかを確認する例として、「ifステートメント」も含まれています。

for f in $(cat 1.txt); do if [ -f $f ]; then rm $f; fi; done

0

ここでは、からのフォルダのセットを使用することができますdeletelist.txtながら、いくつかのパターンを避けるだけでなく

foreach f (cat deletelist.txt)
    rm -rf ls | egrep -v "needthisfile|*.cpp|*.h"
end

0

これにより、ファイル名にスペースを含めることができます(再現可能な例)。

# Select files of interest, here, only text files for ex.
find -type f -exec file {} \; > findresult.txt
grep ": ASCII text$" findresult.txt > textfiles.txt
# leave only the path to the file removing suffix and prefix
sed -i -e 's/:.*$//' textfiles.txt
sed -i -e 's/\.\///' textfiles.txt

#write a script that deletes the files in textfiles.txt
IFS_backup=$IFS
IFS=$(echo "\n\b")
for f in $(cat textfiles.txt); 
do 
rm "$f"; 
done
IFS=$IFS_backup

# save script as "some.sh" and run: sh some.sh

0

誰かがワイルドカード拡張なしsedで削除すること好む場合:

sed -e "s/^\(.*\)$/rm -f -- \'\1\'/" deletelist.txt | /bin/sh

注意:ファイルで絶対パス名を使用するか、正しいディレクトリにいることを確認してください。

そして完全性のためにawk:と同じ

awk '{printf "rm -f -- '\''%s'\''\n",$1}' deletelist.txt | /bin/sh

一重引用符を削除するとワイルドカード展開が機能しますが、ファイル名にスペースが含まれている場合は危険です。これには、ワイルドカードを引用符で囲む必要があります。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.