не можете Вы получать идентификатор процесса и общаться с ним с USR1,
$pgrep -l '^ipchecker.sh$'
который печатает PID Вашего сценария, затем используйте его для
$ kill -USR1 PID
Я понимаю, что USR1 является "определяемым пользователем" сигналом, означая, что, кто бы ни создал программу, может использовать его, чтобы означать, что "закрытие" или "выводит Ваши журналы", или "печатают нечто тысячу раз" или что бы то ни было.
В Вашем сценарии существует довольно много проблем.
Во-первых, для присвоения результата команды к переменной, необходимо включить его любой в обратные галочки (`command`
) или, предпочтительно, $(command)
. У Вас есть он в одинарных кавычках ('command'
) который вместо того, чтобы присвоить результат Вашей команды к Вашей переменной, назначает самой команде строкой. Поэтому Ваш test
на самом деле:
$ echo "test $sum1=$sum2"
test find $i -type f -iname "*.jpg" -exec md5sum {} \;=find $j -type f -iname "*.jpg" -exec md5sum {} \;
Следующий выпуск то, что команда md5sum
возвраты больше, чем просто хеш:
$ md5sum /etc/fstab
46f065563c9e88143fa6fb4d3e42a252 /etc/fstab
Вы только хотите сравнить первое поле, таким образом, необходимо проанализировать md5sum
произведенный путем передачи его посредством команды, которая только печатает первое поле:
find $i -type f -iname "*.png" -exec md5sum '{}' \; | cut -f 1 -d ' '
или
find $i -type f -iname "*.png" -exec md5sum '{}' \; | awk '{print $1}'
Кроме того, find
команда возвратит много соответствий, не всего один, и каждое из тех соответствий будет дублировано вторым find
. Это означает в какой-то момент сравнение того же файла с собой md5sum будет идентичен, и Вы закончите тем, что удалили все свои файлы (я выполнил это на тестовом dir, содержащем a.jpg
и b.jpg
):
for i in $(find . -iname "*.jpg"); do
for j in $(find . -iname "*.jpg"); do
echo "i is: $i and j is: $j"
done
done
i is: ./a.jpg and j is: ./a.jpg ## BAD, will delete a.jpg
i is: ./a.jpg and j is: ./b.jpg
i is: ./b.jpg and j is: ./a.jpg
i is: ./b.jpg and j is: ./b.jpg ## BAD will delete b.jpg
Вы не хотите работать for i in directory_path
если Вы не передаете массив каталогов. Если все эти файлы находятся в том же каталоге, Вы хотите работать for i in $(find directory_path -iname "*.jpg"
) пройти все файлы.
Это - плохая идея использовать for
циклы с выводом находки. Необходимо использовать while
циклы или globbing:
find . -iname "*.jpg" | while read i; do [...] ; done
или, если все Ваше ре файлов в том же каталоге:
for i in *jpg; do [...]; done
В зависимости от Вашей оболочки и опций Вы установили, можно использовать globbing даже для файлов в подкаталогах, но давайте не входить в это здесь.
Наконец, еще необходимо также заключить переменные в кавычки, пути к каталогам с пробелами повредят сценарий.
Имена файлов могут содержать пробелы, новые строки, обратные косые черты и другие странные символы, для контакта с теми, которые правильно в a while
цикл необходимо будет добавить еще некоторые опции. То, что Вы хотите записать, является чем-то как:
find dir_path -type f -iname "*.jpg" -print0 | while IFS= read -r -d '' i; do
find dir_path -type f -iname "*.jpg" -print0 | while IFS= read -r -d '' j; do
if [ "$i" != "$j" ]
then
sum1=$(md5sum "$i" | cut -f 1 -d ' ' )
sum2=$(md5sum "$j" | cut -f 1 -d ' ' )
[ "$sum1" = "$sum2" ] && rm "$j"
fi
done
done
Еще более простой путь был бы:
find directory_path -name "*.jpg" -exec md5sum '{}' + |
perl -ane '$k{$F[0]}++; system("rm $F[1]") if $k{$F[0]}>1'
Лучшая версия, которая может иметь дело с пробелами в именах файлов:
find directory_path -name "*.jpg" -exec md5sum '{}' + |
perl -ane '$k{$F[0]}++; system("rm \"@F[1 .. $#F]\"") if $k{$F[0]}>1'
Этот небольшой сценарий Perl пробежит результаты find
команда (т.е. md5sum и имя файла). -a
опция для perl
разделения вводят строки в пробеле, и сохраняет их в F
массив, таким образом, $F[0]
будет md5sum и $F[1]
имя файла. md5sum сохраняется в хеше k
и сценарий проверяет, был ли хеш уже замечен (if $k{$F[0]}>1
) и удаляет файл, если он имеет (system("rm $F[1]")
).
В то время как это будет работать, это будет очень медленно для больших наборов изображения, и Вы не можете выбрать который файлы сохранить. Существует много программ, которые обрабатывают это более изящным способом включая:
Существует изящная названная программа fdupes
это упрощает целый процесс и предлагает пользователю удаление дубликатов. Я думаю, что это стоит проверить:
$ fdupes --delete DIRECTORY_WITH_DUPLICATES
[1] DIRECTORY_WITH_DUPLICATES/package-0.1-linux.tar.gz
[2] DIRECTORY_WITH_DUPLICATES/package-0.1-linux.tar.gz.1
Set 1 of 1, preserve files [1 - 2, all]: 1
[+] DIRECTORY_WITH_DUPLICATES/package-0.1-linux.tar.gz
[-] DIRECTORY_WITH_DUPLICATES/package-0.1-linux.tar.gz.1
В основном это предложило мне, для которого файла сохранить, я ввел 1, и это удалило второе.
Другие интересные опции:
-r --recurse
for every directory given follow subdirectories encountered within
-N --noprompt
when used together with --delete, preserve the first file in each set of duplicates and delete the others without prompting the user
От Вашего примера Вы, вероятно, хотите выполнить его как:
fdupes --recurse --delete --noprompt DIRECTORY_WITH_DUPLICATES
Посмотрите man fdupes
для всех доступных опций.
unlink
вместо того, чтобы делать asystem
звонить. – Joseph R. 24.11.2013, 20:05$F[1]
. Зафиксированный это с помощью частей массива. Что касается удаляют связь (), я знаю, но требуемый для сведения к минимуму perlisms и системного вызова легче понять, не знаете ли Вы Perl. – terdon♦ 24.11.2013, 20:11