フォルダに/photo
多くのファイルがあるとします。
1.jpg
2.jpg
3.jpg
4.jpg
5.jpg
6.jpg
7.jpg
8.jpg
9.jpg
10.jpg
nodeletelist.txt
このテキストファイルには、削除しないファイルリストの名前とともにファイル名があります。
1.jpg
2.jpg
3.jpg
nodeletelist.txt
ファイルを削除するには:
4.jpg
...
10.jpg
ファイルを除いて1.jpg
、2.jpg
とは何3.jpg
ですか?nodeletelist.txt
nodeletelist.txt
答え1
GNUの発見はありますか?
find photo -mindepth 1 -maxdepth 1 -regextype awk \! -regex ".*/($(tr '\n' '|' < photo/nodeletelist.txt)nodeletelist.txt)" -delete
これはtr(1)
およびを使用して達成されますfind(1)
。
- ファイルを次にリダイレクト
tr
- 改行を「OR」を意味する垂直バーに置き換えます。
- サブシェルから戻る
- ファイルが改行で終わる場合は、最後にフラグ値を追加します。 (この例ではあなたの名前をウォッチャーとして使用するため、
nodeletelist.txt
このソリューションを使用する場合はファイルにファイル名を含める必要はありません。) - ディレクトリ内の1レベル以下のアイテムを検索してください。
photo
- awk正規表現を使用して、上記の手順1〜4で返された文字列を一致させます。
- ファイルの削除いいえ正規表現と一致する(
!
「NOT」を意味するため)
ここに必要な拡張構文がそのフラグに適用されるため、ここのフラグは、、、またはに-regextype
設定することもできます。デフォルトのfindutils正規表現、posix-basic、emacs、sedなどは、このコマンドでは機能しません。posix-extended
egrep
posix-egrep
gnu-awk
posix-awk
答え2
zsh
それがオプションであれば、次のように使用するシェル関数を定義できます。グローバル予選"は、glob内のすべてのファイルのリストをフィルタリングするために使用されます*
。
% cmd() { ! grep -qF "$REPLY" ./nodeletelist.txt ; }
その後(photo/
ディレクトリから)
% ls
10.jpg 1.jpg 2.jpg 3.jpg 4.jpg 5.jpg 6.jpg 7.jpg 8.jpg 9.jpg nodeletelist.txt
% ls *(+cmd)
10.jpg 4.jpg 5.jpg 6.jpg 7.jpg 8.jpg 9.jpg
大丈夫に見えますが、削除しましょう。
% rm *(+cmd)
% ls
1.jpg 2.jpg 3.jpg nodeletelist.txt
まず、ファイルを配列にマップし、そのファイルが配列の要素であるかどうかを$REPLY
テストするより効率的な実装があります。
答え3
私にとっては最も簡単で覚えやすく、多くのファイルでも動作します(ファイル名の改行で考えが壊れる可能性がありますが、その場合はリストについて考える必要があります)。
cd /photo
ls -1 | grep -v -x -f nodeletelist.txt | xargs -d "\n" -P 0 rm -f
ディレクトリに他のエントリ(サブディレクトリまたは他のファイル、リストにtxtが含まれていると仮定しない)がある場合は、lsの代わりにfind Iを使用します(find . -maxdepth 1 -type f -name "*.jpg"
例:)。
答え4
説明された名前にスペースがない場合
rm $(join -v 1 <(ls *.jpg) <(sed '$ d' nodeletelist.txt))
nodeletelist.txt ファイルの最後の行を実際に読み込んだとします。nodeletelist.txt
そうでなければ、
rm $(join -v 1 <(ls *.jpg) nodelete.txt)
しかし、あまり高級感はありません...