Передача по каналу вывода к текстовому файлу в для цикла

$ # является количеством аргументов оболочке. Так, первая строка говорит "выход, если нет 3 аргументов", потому что правильная часть (после ||) только выполняется, если левая часть не верна. || логическое или.

255, поскольку код возврата может быть произвольным.

сценарии возвратятся 0, если слово "строка" будет во входе.

Это помогает?

4
15.03.2013, 17:14
5 ответов

Действительно нет никакой потребности в репродуцировании findпроизведите цикл оболочки INA. Если Вы хотите упаковать список имен файлов, универсальная формула:

find ... | gzip > logfile.gz

Если Вы хотите к gzip сами файлы, он изменяется на:

find ... | tar -czvf archive.tar.gz -T -

который говорит tar прочитать список имен файлов, чтобы продолжить работать из файла и сингла - обозначает стандартный вход. ( -T Иначе --files-from= опция присутствует в tar GNU, я не уверен в других ароматах.), Конечно, это повреждается, если Вам удается работать над файлами, которые содержат \n на их имена.

4
27.01.2020, 20:47

Вы не можете выполнить последующую обработку вывод находки надежно. Использовать -exec в find:

find . -type f ! -name '*.gz' ! -name '*.Z' -mtime +7 -exec sh -c '
  for i do
    printf "%s\n" "Will be compressing file $i"
    gzip "$i"
  done' sh {} + >> log

С реализацией GNU find, можно даже уйти, не работая sh:

find . -type f ! -name '*.gz' ! -name '*.Z' -mtime +7 \
  -printf 'Will be compressing file %p\n' -exec gzip {} + >> log
4
27.01.2020, 20:47
  • 1
    Хороший совет, но я озадачен: почему сценарий как не отправляется, работая (принимающий ручные имена файлов)? –  Gilles 'SO- stop being evil' 16.03.2013, 00:12
  • 2
    @Gilles, Который я не знаю также. Это пахнет как конец долгой недельной пользовательской ошибки, где Вы не смотрите на файл, Вы думали, что были. Или это мог быть другой процесс, который усекает или воссоздает тот же файл тем временем. –  Stéphane Chazelas 16.03.2013, 00:19
  • 3
    , я смотрю на корректные файлы, потому что, если я удаляю оператор для передачи по каналу вывода в файл, список файлов, отображенных на экране, является желаемым списком файлов. Мое исходное сообщение не было четким - я приношу извинения. –  morgan_g 16.03.2013, 09:12
  • 4
    Моя проблема с использованием - исполнительная опция состоит в том, что это изменяет результат предыдущего оператора находки. Если я выполняю команду находки как тип в моем сообщении при приглашении оболочки, то это отображает корректный список файлов, Если я добавляю "-должностное лицо ls - al {} \"; затем отображенный список заметно отличается. Я подозреваю однако, что буду отправлять отдельный вопрос об этом. –  morgan_g 16.03.2013, 09:21
  • 5
    О каком основании Вы делаете комментарий? Вы не можете выполнить последующую обработку вывод находки надежно. Я использую подобные команды, чтобы переместить файлы, монтировать файловые системы и т.д. регулярно в ежедневной работе. –  morgan_g 16.03.2013, 09:23

поместите свое перенаправление (>>) вне цикла (после того, как done) как так:

for i in $(find . -type f \( ! -name '*.gz' \) -a \( ! -name '*.Z' \) -mtime +7);
  do echo "Will be compressing file  ${i}";
  ##gzip $i;
done >> $LOGCLEAN_FILE

Или, если Вы планируете возможный некомментарий Вашего gzip команда Вы могли бы рассмотреть:

for i in $(find . -type f \( ! -name '*.gz' \) -a \( ! -name '*.Z' \) -mtime +7);
  do gzip "$i" && echo "Successfully compressed ${i}";
done >> $LOGCLEAN_FILE

&& средства только делают следующую команду, если предыдущая команда выходит с 0 (никакая ошибка).

2
27.01.2020, 20:47
  • 1
    Протестирует, после того как я вернулся за своим столом. Спасибо за обратную связь –  morgan_g 16.03.2013, 08:53
  • 2
    Это не обращается к выводу передачи по каналу в для цикла! –  ThorSummoner 01.02.2015, 04:14

Поскольку имена файлов могут иметь и пробелы и новые строки, которыми был бы вероятный подход:

#!/bin/bash

logclean_file="logclean_file.txt"

ts="$(date)"

printf "%s\n" "$ts" > "$logclean_file"

# Set IFS blank
# -r Backslash does not act as an escape character. The  backslash
#    is  considered  to be part of the line.  In particular, a
#    back-slash-newline pair may not be used as a line continuation.
# -d delim
#    The  first  character  of  delim is used to terminate the input
#    line, rather than newline.
# 
# Here setting -d to nul or 0x00. This enables us to capture any file-
# names with the print0 from find.
#
# fn The variable to read into.
#
while IFS= read -r -d $'\x00' fn; do
    printf "Will perhaps be compressing file %s\n" "$fn" >> "$logclean_file"
    # If file + gz does not exist 
    if [[ ! -e "$fn.gz" ]]; then
            if gzip command "$fn"; then
                    echo "Horray! success!" >> "$logclean_file"
            else
                    echo "Harf! Gzip failed." >> "$logclean_file"
            fi
    else
            echo "Nah. Already exists." >> "$logclean_file"
    fi
done < <(find . -type f \( ! -name '*.gz' \) -a \( ! -name '*.Z' \) -print0)
# Notice -print0 at end which means find will print filenames, - separating
# them with 0x00 instead of new-line

О мобильности:

Ни один echo ни print являются действительно портативными. В то время как print уникально для ksh93, echo только был стандартизирован очень поздно в процессе POSIX, и на более старые версии нельзя полагаться для приведения к предсказуемым результатам. Посмотрите эхо по сравнению с печатью и Почему printf лучше....

printf "Some %s\n" "$var" >> "$foo"
# Or
echo "Some $var" >> "$foo"

О стиле:

  • переменные кавычки.
  • Рассмотрите использование нижнего регистра пользовательских переменных (Ваши собственные переменные).

Некоторые касательно:

Для руководств TLDP, и если бы Вы используете стильный, я рекомендовал бы один из них для чтения экрана.

1
27.01.2020, 20:47
  • 1
    Никто не упомянул bash. print ksh (и zsh) команда. –  Stéphane Chazelas 15.03.2013, 22:33
  • 2
    @StephaneChazelas: О, блин. Иногда у меня, кажется, есть чрезвычайно выборочное зрение. Как я пропускал это? - Ну, Спасибо за исправление меня, - я удалю :) –  Runium 16.03.2013, 09:03
  • 3
    @Sukminder - благодарит за ссылки Greycat на кавычки оболочки. Это - хороший ресурс. –  Henk Langeveld 17.03.2013, 15:06
  • 4
    Благодаря всем для совета проверит ссылки –  morgan_g 18.03.2013, 13:39
  • 5
    @HenkLangeveld: Спасибо за редактирование! Я не удалю, в конце концов, затем. –  Runium 20.03.2013, 02:39

Также короткий и сладкий: cat list | xargs rm

Это предполагает, что у вас есть файл с именем 'list' из всех вредоносных PHP-файлов и что вы находитесь в каталоге, содержащем PHP-файлы (просто чтобы быть понятным, но я уверен, вы уже поняли это).


Если какое-либо из имен файлов содержит новые строки, это будет опасно для запуска , особенно потому, что вы уже знаете, что они были созданы вредоносным противником. Если у вас есть список имен файлов в текстовом файле, вы можете проверить список заранее и убедиться, что ни одна из строк не удалит файлы, которые вы хотите сохранить.

Кроме того, если злоумышленнику удалось получить вредоносные php-скрипты на этом хосте, это может быть не самой большой вашей проблемой . Я только отвечаю на ваш вопрос, и @ soubunmei дал лучший ответ, потому что она знала немного больше о команде найти, чем я, но ни один из ответов не гарантирует безопасность . Извините, если это не было ясно, и спасибо @ soubunmei и @ SoubingHomer за то, что указали на мой неосторожный язык. Вы должны поговорить с профессионалом по кибербезопасности, если вы считаете, что кто-то из злоумышленников мог получить повышенные привилегии на хосте.


Я лично подозреваю, что есть хороший способ, основанный на «продлении и дате», чтобы сделать это, как вы просили, что некоторые люди могут найти более элегантным, но так как у вас уже есть список, почему бы не использовать его?

Я протестировал это на файл под названием «список», который содержал строки:

file1
file2

и эти файлы были на моем рабочем столе. Это сработало, как и ожидалось. Я настоятельно рекомендую сначала протестировать его на малой ступени, чтобы увидеть, как он будет себя вести, а также создать резервную копию каталога перед любым массовым удалением файлов. Место на жестком диске намного дешевле времени программистов!

-121--209995-

Для определенных пакетов (те, которые я, скорее всего, не хочу взламывать), я делаю свой собственный пакет, используя это:

https://github.com/bluepeppers/pip2arch

затем построить и установить произведенный PKGBUILD.

Я оставляю virtualenvs для пакетов, которые я могу изменить или взломать.

-121--12149-

Если вы пытаетесь перейти к выходному файлу, выполняется итерация по пути к файлу...

Используйте возможности find's exec

... для обработки итераций.

Я хотел выполнить итерацию по явным файлам перечислять через вложенную оболочку, и вызвать expand , который выводит stdout, и перезаписать каждый отдельный файл. Проблема, решаемая этим ответом .

find $(git ls-files | grep '.py$') \
    -exec bash -c 'expand -t 4 "$0" > /tmp/e && mv /tmp/e "$0"' {} \;

Я представляю немного измененную версию этого ответа, так как другие ответы в этом потоке не предоставляют решения общего назначения. Это единственное, что я видел, что работает, что применимо только при итерации по пути к файлу.

Я могу представить себе решение, которое злоупотребляет созданием файлов, названных в честь предметов итерации, чтобы можно было выполнить итерацию над этим именем с помощью поиска.


Неудачная попытка:

Как и вызов find exec, я попытался использовать bash -c... внутри шлейфа for. Но я столкнулся с той же проблемой пустых выходных файлов.

Отказ от ответственности: Я не уверен, в чем именно была моя проблема, во всех попытках до использования find exec, все выходные файлы, в которые я ожидал быть записанным, были перезаписаны, моя проблема была в том, что они были пустыми после.

0
27.01.2020, 20:47

Теги

Похожие вопросы