年と月ごとにサブフォルダーに並べ替えられた 500,000 個のイメージを持つフォルダーがあります。これを行うスクリプトを作成したいと思います。
ファイル名の場合確かにファイル名を一致させ、names.log
ファイルを削除します。
names.log
ファイル名が含まれます。例:
image1.jpg
photo3.jpg
redcar.jpg
balloon2323.jpg
ちょっと…保存したいファイル名が10,000個あります。
私のサーバーにはPHPとPythonがありますが、これに最も適したものが何であるかわかりません。私は以前は何のスクリプトも書いていませんでした。誰かがこれを行うコードを提供し、それを実行する方法を教えてもらえますか?それともコマンドで達成できますか?
答え1
これはPythonでは非常に簡単です。os.walk
。警告、テストされていないコードです。名前リストには、1行につき1つの名前が含まれているとします。
#!/usr/bin/python2
import os
names_file = open('names.log')
names = set(line.rstrip('\n') for line in names_file.readlines())
names_file.close()
for root, dirs, files in os.walk('/path/to/top/directory'):
for name in files:
path = os.path.join(root, name)
if os.path.isfile(path):
if name not in names:
print path
#os.remove(path) # uncomment this line if you're happy with the set of files to remove
答え2
find -name '*.jpg' -print0 | grep -zZ -vf name.log | xargs -0 COMMAND
必要に応じて交換COMMAND
してくださいls -l
rm
編集する: 提供されたコマンドは、name.log を正規表現セットとして扱います。 @terdon name.logはファイル名のリストであることを忘れないでください。
ファイル名が一般的な「一般」文字を使用している場合は十分ですが、次の場合に問題が発生する可能性があります。
- ファイル名/正規表現には、などの珍しい文字が含まれています
[
。]
(この場合、一部のファイルの削除が失敗する可能性があり、名前付きの一部のファイルが削除される可能性があります。name.log
)これを防ぐために、grep -F
特殊文字を使用または保護できますname.log
。 - 正規表現はファイル名の部分文字列と一致します(この場合、一部のファイルは削除されません。
a.jpg
「a」で終わるすべての画像と一致します(たとえば、、camera.jpg
)banana.jpg
。
ケース2の場合プレフィックスケースの場合 - 正規表現の先頭に「/」を追加できます。
sed 's!^!/!' name.log > new.log
find -name '*.jpg' -print0 | grep -F -zZ -vf new.log | xargs -0 COMMAND
でも
find -name '*.jpg' -print0 | grep -zZFvf <(sed 's!^!/!' name.log) | xargs COMMAND
ケース2の場合、イメージファイルに拡張子があるため、サフィックスのケースはそれほど重要ではありません。この状況を正しく解決するには、「ファイル名の後には何もありません」と言う必要があります。正規表現が必要で、.
[
]
ファイル名の特殊文字(example)を保護する必要があります。
sed -re 's!([].[])!\\\1!g; s!.*!/&$!' name.log > new.log
find -name '*.jpg' -print0 | grep -zZ -vf new.log | xargs -0 COMMAND
答え3
これは本物.pax
作成-s
中にファイル名を変更する代替オプションの概念があります。-s
複数の代替パラメータを指定することもできます。そして、ここで最も関連性が高いのは、選択したメンバーが成功した一致に必要な代替-s
パラメータのみを適用しますが、ファイル名が空の代替項目によって一致するファイルが選択されないことです。
展示する:
mkdir test; cd test
touch match nomatch
pax -ws '|^.*/match$|&|' -s '|.*||' ./ |
pax -v
上記のコードは./test
ディレクトリを作成および変更し、2つのファイルを作成し、パイプにアーカイブを書き込みます。-w
ここで、2番目のファイルはパイプの内容を詳しく説明します。上記は次のとおりです。tar
pax
pax
-v
-rw-r--r-- 1 mikeserv mikeserv 0 Feb 22 11:40 ./
..../match
一致するから今後最後の置換はファイル名のすべての文字を置き換えます。
そしてpax
、実際にファイルの内容をそのアーカイブにコピーする必要はありません。-rwl
ハードリンクを生成するコピー操作を使用できます。
したがって、ファイル名がpaxscript
次のような場合...
cd -- "$1"
pax -rwvl \
-s '|^.*/image1\.jpg$|&|' \
-s '|^.*/photo3\.jpg$|&|' \
-s '|^.*/redcar\.jpg$|&|' \
-s '|^.*/balloon2323\.jpg$|&|' \
-s '|.*||' ./ ../"${1##*/}.mirror"
cd - >/dev/null
...そしてこれを実行すると...
. ./paxscript "$targetdir"
"$targetdir"
一致させたいファイル名へのハードリンクのみを含む親ディレクトリにミラーを作成します。その後、実行する前に結果が必要に応じて表示されることを確認し、rm -rf "$targetdir"
不要なパス名を削除できます。
答え4
満足している場合は、bash
次のアルゴリズムを提供したいと思います(すべてのスクリプト言語で実装可能)。
- 現在のファイルのリストを作成します。
find /path_to_folder -name "*.jpg" -fprint files.tmp
- 基準で並べ替え
files.tmp
と比較name.log
comm -23 files.tmp name.log
files.tmp
rm
to コマンドに関連するファイルのリストを渡します。
ファイルパスを書き留めます。ファイルパスは、両方で同じであることがfiles.tmp
できますname.log
(全体またはフォルダごと)。この場合、ファイル名の区切り文字name.log
はnewline
。