Я знаю, что это старый пост, но почему бы просто не сделать это?
echo "hi" >> log.txt #stdout -> log
echo "hi" | tee -a log.txt #stdout -> log & stdout
echo "hi" &>> log.txt #stdout & stderr -> log
echo "hi" |& tee -a log.txt #stdout & stderr -> log & stdout
И, конечно же, если вам нужен стандартный вывод, вы можете просто регулярно печатать.
Вы можете сделать это с любой комбинацией потоков, просто используя эти две основные команды.
Я знаю, что я пришел сюда и не получил простой для понимания/реализовать ответ, надеюсь, это поможет кому-то еще, кто борется.
Между прочим, для нубов, таких как мой предыдущий я, все, что делает команда tee
, это выводит ввод stdin как на stdout, так и в файл (s ), указанный в качестве последующих аргументов. -a
означает добавление, поэтому вы не перезаписываете файл при каждом использовании команды. Если у вас есть дополнительные вопросы, я считаю этот очень полезным ресурсом для быстрого изучения bash.
Вы должны использовать разделитель для файла, содержащего два поля в строке. Здесь sed
вставляет этот разделитель, и результат передается строка за строкой в mv
#!/bin/bash
while read -r oldname newname; do
[ -f "${oldname}.png" ] && echo mv -- "${oldname}.png" "${newname}.png"
done < <(sed 's/^[0-9]*/& /' upcs.txt)
Снимите echo
после тестирования. Конечно, я предполагаю, что ваше первое поле всегда представляет собой последовательность цифр, а второе поле не имеет пробелов, не начинается с цифры и т. д.
Если вам нужны какие-либо дополнительные действия, например, проверка на наличие повторяющихся имен целей, вы можете сделать это в первую очередь над файлом. Или, если вам нужно, в любом случае mv
не перезаписывать существующую цель, используйте -n
(--no-clobber
), также-i
(--interactive
)будет запрашивать ввод пользователя по той же причине.
Один из способов следующий. Но обратите внимание, что это выглядит файлы только в текущем каталоге и не переходят в подкаталоги.
while IFS= read -r l <&3
do
barcode=${l%%[!0-9]*}
value=${l#"$barcode"}
[ -f "$barcode.png" ] && \
printf '%s.png ' "$barcode" "$value"
done 3< upcs.txt | xargs -rn 2 -t cp -pdf --
В вашем сценарии переменная $f будет иметь вид 052100029962.png, который не соответствует ни одной из строк upcs.txt:
052100029962.png doesn't match *052100029962mccormickpepper*
Предполагая, что номера UPC всегда имеют длину 12 символов или что названия продуктов не начинаются с цифры, я бы перебирал строки текстового файла, разделял строку с помощью регулярного выражения, искал имя файла {$upc}.png и переименуйте его в {$product _name}.png.
#!/bin/bash
while read -r line; do
if [[ $line =~ ([0-9]{12})(.*) ]]; then
upc="${BASH_REMATCH[1]}.png"
name="${BASH_REMATCH[2]}.png"
if [[ -f $upc ]]; then
if [[ ! -f $name ]]; then
cp "$upc" "$name"
else
echo "$name already exists"
fi
fi
fi
done < upcs.txt