Я понял, я тоже должен заключить команду в круглые скобки,
mytime=$(time (for i in {1..3}; do curl -s -w '\n' -XPOST -H 'Content-Type: application/x-www-form-urlencoded' --data-urlencode query='select distinct ?Concept where {[] a ?Concept} LIMIT 100' http://143.233.226.61:443/sparql > /dev/null; done) 2>&1 1>/dev/null)
trap break INT
перед циклом:
hashes=
trap break INT
for file in *; do
hashes+=$(md5sum -- "$file")$'\n'
done
trap - INT
echo "$hashes" > hashes.txt
Я исправил некоторые сомнительные вещи в вашем скрипте ($(ls)
,"\n"
).
FWIW, такой "нелокальный разрыв" не работает в mksh
или yash
, но работает в bash
, dash
, zsh
и ksh93
.
trap ctrl_c INT
ctrl_c() {
echo "$hashes" > hashes.txt
exit 0
}
Кстати, я бы не использовал ls
для получения списка файлов, а что-то вроде for file in *; do
.
Вы никогда не должны использовать выходные данные ls
в качестве входных данных для другой программы. Это не работает (для любого определения «работы», включающего понятия надежности или безопасности ), и нет никогда никакой необходимости делать это, потому что оболочка выполняет подстановку (т.е. расширение подстановочных знаков )выполняет работу, которую вы пытаетесь выполнить с помощью mis -с использованием ls
. См. Почему не разборls
(и что делать вместо )? .
Если вы должны сделать что-то подобное, используйте find... -exec {} +
или find... -print0 | xargs -0r...
, а неls
-любой из них действительно будет работать и работать безопасно, независимо от того, какие символы есть в именах файлов.
Ваш цикл for
должен быть записан как:
for file in *; do
...
done
Вам даже не нужен цикл for
, если только вы не собираетесь делать что-то еще с каждым $file
внутри цикла.
Вот несколько альтернативных способов сделать то, что делает ваш цикл for, сохраняя вывод md5sum
в массив с именем hashes
и затем выводя его:
с помощьюprintf
:
$ hashes=( $( md5sum * ) )
$ printf '%s %s\n' "${hashes[@]}" > hashes.txt
$ cat hashes.txt
b026324c6904b2a9cb4b88d6d61c81d1 file.1
26ab0db90d72e28ad0ba1e22ee510510 file.2
6d7fce9fee471194aa8b5b6e47267f03 file.3
Обратите внимание, что в строке формата printf
есть два %s
, разделенных двумя пробелами. Это даст тот же результат, что и сам md5sum
.
Кстати, вы можете увидеть, как записи хранятся в массиве с помощьюtypeset -p
:
$ typeset -p hashes
declare -a hashes=([0]="b026324c6904b2a9cb4b88d6d61c81d1" [1]="file.1"
[2]="26ab0db90d72e28ad0ba1e22ee510510" [3]="file.2"
[4]="6d7fce9fee471194aa8b5b6e47267f03" [5]="file.3")
Оболочка разделила вывод md5sum
на слова (, как определено значением переменной оболочки $IFS
), и поместила каждое «слово» в отдельный элемент массива.
с помощьюtee
:
$ hashes=( $( md5sum * | tee hashes.txt) )
$ cat hashes.txt
b026324c6904b2a9cb4b88d6d61c81d1 file.1
26ab0db90d72e28ad0ba1e22ee510510 file.2
6d7fce9fee471194aa8b5b6e47267f03 file.3
Зная это, ответ-ловушка Лассе Климана может быть записан как:
trap ctrl_c INT
ctrl_c() {
printf '%s %s\n' "${hashes[@]}" > hashes.txt
exit 0
}
Впрочем, здесь даже ловушка не нужна. md5sum
с tee
сделают то, что вы хотите -, т.е.одновременно заполнить $hashes
И файл hashes.txt
.
Или, если вы не хотите использовать массив:
$ for file in *; do
hashes+="$(md5sum "$file" | tee -a hashes.txt)"$'\n'
done
$ echo "$hashes"
b026324c6904b2a9cb4b88d6d61c81d1 file.1
26ab0db90d72e28ad0ba1e22ee510510 file.2
6d7fce9fee471194aa8b5b6e47267f03 file.3
Здесь мы используем опцию tee
's -a
(--append
), потому что мы запускаем md5sum
в цикле и не хотим, чтобы каждая итерация перезаписывала файл hashes.txt
.
Примечание :Это всегда будет иметь дополнительную пустую строку в конце строки $hashes
, увеличивая количество строк на 1. Этого не будет при использовании массива.