重複したファイルがたくさんあります。ファイルは次のようになります。
dsc_0364_5723957929_o.jpg
dsc_0364_5294988157_o.jpg
dsc_0365_2464873748_o.jpg
dsc_0365_2853758327_o.jpg
....
同じプレフィックスを持つ2番目(時には3番目)のファイルを削除したいと思います。どうすればいいですか?
答え1
以下でgawk
使用できます。find
xargs
find -maxdepth 1 -type f -name 'dsc*jpg' -print0 |
gawk 'BEGIN { RS=ORS="\0" ; FS="_" } seen[$2]++' |
xargs -0 rm
レコード区切り文字として NUL を使用するのは AFAIK です。GNU awkでのみサポートされています。(gawk
)。
答え2
このソリューションは、すべてのファイルが同じパターンに従う場合に機能します。つまり、プレフィックスを取得するにはstring_string_string_string.string
ファイル名に3つが必要です。_
たとえば、dsc_0360_5294988157_o.jpg
ファイル名があります。 I want to get its prefix dsc_0360
.
次のスクリプトが機能するはずです。
#! /usr/bin/env bash
lastPrefix=''
for i in ./* ; do
prefix=${i%_*_*}
if [[ $prefix == $lastPrefix ]];then
rm $i
else
lastPrefix=$prefix
fi
done
この行を使用してprefix=${i%_*_*}
ファイル名のプレフィックスを取得し、以前に同じプレフィックスが設定されているかどうかを比較します。その場合は、ファイルを削除する必要があります。
for i in ./* ;
作業ディレクトリを変更する必要があるかもしれません。for i in /path/to/your/working_directory ;
答え3
すでに見たファイル名のプレフィックスを追跡するには、連想配列を使用する必要があります。たとえば、
#!/bin/bash
# define $seen as an associative array (-A).
declare -A seen
for f in dsc_* ; do
# derive a value for $prefix by removing the last
# two _ sections from $f, e.g. remove '_5723957929_o.jpg'
prefix=${f%_*_*}
# test if "$seen"'s element for this "$prefix" is empty:
if [ -z "${seen[$prefix]}" ] ; then
# if it is, then we haven't seen this prefix before, so
# we need to remember it.
seen[$prefix]="$f"
# optional debugging output. delete or comment out if
# not needed.
echo "seen[$prefix] = $f"
else
# Dry-run showing which files would be deleted.
# remove the echo to actually delete it. Optionally
# add -v for verbose output.
echo rm -f "$f"
fi
done
サンプルファイル名を含むディレクトリで実行すると、次の出力が生成されます。
seen[dsc_0364] = dsc_0364_5294988157_o.jpg
rm -f dsc_0364_5723957929_o.jpg
seen[dsc_0365] = dsc_0365_2464873748_o.jpg
rm -f dsc_0365_2853758327_o.jpg
デバッグ出力なしで実行され、詳細出力に置き換えられるecho rm -f
と、rm -fv
次の出力が生成されます。
removed 'dsc_0364_5723957929_o.jpg'
removed 'dsc_0365_2853758327_o.jpg'
それ以外の場合は-v
ファイルを削除しますが、まったく出力を生成しません。