Замена команды in for loop не работает

Я хочу сохранить все файлы, не заканчивающиеся на .bat

Я пытался

 for f in $(ls | egrep -v .bat); do echo $f; done 

а также

 for f in $(eval ls | egrep -v .bat); do echo $f; done 

Но оба подхода дают одинаковый результат, поскольку они печатают все. В то время как ls | egrep -v .bat ls | egrep -v .bat и eval ls | egrep -v .bat eval ls | egrep -v .bat работа сама по себе, если используется отдельно от цикла for .

РЕДАКТИРОВАТЬ

Интересно видеть, что если я -v флаг -v , цикл выполняет все, что нужно, и перечисляет все файлы, заканчивающиеся на .bat .


Не стесняйтесь редактировать заголовок вопроса, так как я не был уверен, в чем проблема.

Я использую GNU bash, version 4.1.10(4)-release (i686-pc-cygwin).


ПРИМЕР

 $ ls -l | egrep -v ".bat" total 60K -rwx------+ 1 SYSTEM SYSTEM 5.3K Jun 6 20:31 fsc* -rwx------+ 1 SYSTEM SYSTEM 5.3K Jun 6 20:31 scala* -rwx------+ 1 SYSTEM SYSTEM 5.3K Jun 6 20:31 scalac* -rwx------+ 1 SYSTEM SYSTEM 5.3K Jun 6 20:31 scaladoc* -rwx------+ 1 SYSTEM SYSTEM 5.3K Jun 6 20:31 scalap* 

Команда работает, но не в цикле for.

 $ for f in $(ls | egrep -v .bat); do echo $f; done fsc fsc.bat scala scala.bat scalac scalac.bat scaladoc scaladoc.bat scalap scalap.bat scalac scalac.bat scaladoc scaladoc.bat scalap scalap.bat 

DEBUG $ set -x

 mike@pc /cygdrive/c/Program Files (x86)/scala/bin $ for f in $(ls | egrep -v .bat); do echo $f; done ++ ls -hF --color=tty ++ egrep --color=auto -v .bat + for f in '$(ls | egrep -v .bat)' + echo fsc fsc + for f in '$(ls | egrep -v .bat)' + echo fsc.bat fsc.bat // and so on 

  • Количество строк, выводимых ls
  • правильный способ перебора содержимого в каталоге
  • Как открыть все файлы, которые являются результатом команды ls?
  • Почему мой «ls -al / home» не работает?
  • Найдите данные о емкости и самый старый файл в формате Busybox
  • Доверенная файловая система для отказа автомонтирования
  • Ls -1 Команда в linux на Ubuntu dosen't показывает подробности рядом с именем каждого каталога или файла в списке?
  • Как отключить мигание имен файлов в rlogin
  • 3 Solutions collect form web for “Замена команды in for loop не работает”

    В вашем коде несколько ошибок:

    Использование замены без кавычек ( $(...) ) без установки $IFS

    Выделение разворота без кавычек – это оператор split + glob. По умолчанию используется разделение на пространство, вкладку и новую строку. Здесь вы хотите разделить только на новую строку, поэтому вам нужно установить IFS, так как иначе это означает, что не будет работать должным образом, если имена файлов содержат пробелы или символы табуляции

    Использование подменю без кавычек без set -f .

    Выделение разворота без кавычек – это оператор split + glob. Здесь вы не хотите глотания, то есть расширение подстановочных знаков, таких как scala* в список совпадающих файлов. Если вы не хотите, чтобы оболочка делала глобусы, вы должны отключить ее с помощью set -f

    ls aliased to ls -F

    Вышеупомянутый вопрос усугубляется тем фактом, что вы перешли к ls -F . Что добавляет / в каталоги и * в исполняемые файлы. Итак, как правило, поскольку scala является исполняемым, ls -F выводит scala* , а в качестве шаблона глобуса он расширяется до всех имен файлов, начинающихся с scala что объясняет, почему это похоже на то, что egrep -v не фильтрует файлы.

    Предполагая, что имена файлов не содержат символов новой строки

    newline является действительным символом, как любой в имени файла. Поэтому синтаксический анализ вывода ls обычно не работает . Например, вывод ls в каталоге, который содержит файлы a и b такой же, как в каталоге, который содержит один файл с именем a\nb .

    Выше egrep будет фильтровать строки имен файлов, а не имена файлов

    Использование egrep вместо grep -E

    egrep устарел. grep -E является стандартным эквивалентом.

    Не убежать . регулярный оператор.

    Выше вы использовали egrep для включения расширенных регулярных выражений, но вы не используете какой-либо расширенный RE-специфический оператор. Единственный оператор RE, который вы используете . чтобы соответствовать любому персонажу, хотя похоже, что это не то, что вы намеревались. Таким образом, вы могли бы использовать grep -F здесь. Или используйте grep -v '\.bat' .

    Не привязывать регулярное выражение к концу строки

    egrep .bat будет соответствовать любой строке, содержащей любой символ, за которым следует bat , поэтому это регулярное выражение означает все, что содержит bat не в первой позиции. Это должен был быть grep -v '\.bat$' .

    Оставляя $f unquoted

    Выход из функции без кавычек – это оператор split + glob. Там вы не хотите ни одного, поэтому $f следует указывать ( "$f" ).

    Использовать echo

    echo расширяет escape-последовательности ANSI C в своих аргументах и ​​/ или обрабатывает строки типа -n или -e специально в зависимости от реализации echo (и / или среды).

    Вместо этого используйте printf .

    Поэтому лучшее решение:

     for f in *; do case $f in (*.bat);; (*) printf '%s\n' "$f" esac done 

    Хотя, если в текущем каталоге нет не скрытого файла, это все равно будет выводиться * . Вы можете обойти это в zsh , изменив * на *(N) или в bash , запустив shopt -s nullglob .

    Вы не должны использовать ls для разбора файлов таким образом.

    Сначала установите extglob globstar через shopt -s extglob globstar затем

     for f in !(*.bat) do printf '%s\n' "$f" done 

    Использование find

     find . -type f ! -name '*.bat' 

    Используйте оператор отрицания для более безопасного обращения с файлами.

    В вашем цикле for ничего нет:

     $ for f in $(ls | egrep -v .bat); do echo $f; done 

    Вот мой вывод для приведенной выше команды:

     $ for f in $(ls | egrep -v .bat); do echo $f; done fsc scala scalac scaladoc scalap 

    Возможное исправление

    Одним из предложений было бы привести аргумент egrep , например:

     $ for f in $(ls | egrep -v '.bat'); do echo $f; done 

    Также взгляните на вики Bash Pitfalls для других потенциальных проблем при написании сценариев в Bash, таких как это. В частности, это звучит как самая правдоподобная причина, по которой вы сталкиваетесь с этой проблемой. Проверьте, не содержат ли какие-либо из ваших файлов пробелы.

    отладка

    Еще одна вещь, которую нужно попробовать – включить подробную отладку вашей команды bash, прежде чем запускать ее, чтобы вы могли видеть, что происходит за кулисами.

    Это позволяет отлаживать:

     $ set -x 

    Затем запустите команду:

     $ for f in $(ls | egrep -v .bat); do echo $f; done ++ ls --color=auto ++ egrep --color=auto -v .bat + for f in '$(ls | egrep -v .bat)' + echo fsc fsc + for f in '$(ls | egrep -v .bat)' + echo scala scala + for f in '$(ls | egrep -v .bat)' + echo scalac scalac + for f in '$(ls | egrep -v .bat)' + echo scaladoc scaladoc + for f in '$(ls | egrep -v .bat)' + echo scalap scalap 

    Затем отключите его:

     $ set +x 

    Проблема с Cygwin?

    Учитывая, что примеры хорошо работают на ряде родных систем Linux, проблема, скорее всего, связана с тем, что она связана с Cygwin и / или конкретными версиями bash и egrep . Я бы обратил особое внимание на разделитель полей в Bash, $IFS чтобы узнать, существует ли проблема между различными разделителями строк в Windows ( 0x0d,0x0a ) и Unix ( 0x0a ).

    У меня нет установки Cygwin, поэтому у меня нет метода доказательства этой гипотезы.

    Interesting Posts

    Самый чистый способ использования смартфона как обычной рабочей станции Linux

    захватить идентификатор процесса, который вызвал функцию внутри функции

    Используйте nautilus вместо thunar с папками для рабочего стола?

    В zsh, как я могу быстрее отказаться от процесса переднего плана?

    эффективная функция командной строки файла cross-os

    Получение ошибки «Bad file descriptor» во время tar

    как я могу сделать trisquel похожим на gnome 3?

    bash для переменной цикла, не меняющейся

    Почему некоторые linux-инструменты записывают в STDERR вместо STDOUT по умолчанию?

    chroot segfault

    Резервное копирование файлов с помощью команды tar и индикатора выполнения?

    Как значить xterm, когда он теряет фокус?

    Получение emacs для конвертирования латекса на лету?

    vsftpd: используйте Явный SSL в другом порту, чем незашифрованный FTP

    Я только что приобрел VPS: что я должен сделать первым, чтобы защитить его

    Linux и Unix - лучшая ОС в мире.