Замена команды в для цикла, не работающего

Я быть бы Вы восстанавливать версию, обеспеченную дистрибутивом. Поэтому существует по крайней мере некоторая гарантия, что кто-то, предположительно, осторожный на самом деле протестировал ту версию на самом дистрибутиве.

Относительно управления версиями эпоха является одной идеей, но я предпочитаю, чтобы Вы изменили версию на что-то как 2:1.0~rc3+svn20090426-1ubuntu16.1custom1, просто ради ясности. Таким образом, если Вы хотите препятствовать тому, чтобы обновления дистрибутива установили нетронутые (созданные из дистрибутива) пакеты...

4
26.08.2013, 20:07
3 ответа

Несколько вещей неправильно в Вашем коде:

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

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

Используя неупомянутую замену команды без set -f.

Отъезд закрывших кавычки расширений является split+glob оператором. Здесь Вы не хотите globbing, который является расширением подстановочных знаков такой как scala* в список соответствия файлам. Когда Вы не хотите, чтобы оболочка сделала globbing, необходимо отключить его с set -f

ls искаженный к ls -F

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

Принимающие имена файлов не содержат символы новой строки

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

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

Используя egrep вместо grep -E

egrep удерживается от использования. grep -E стандартный эквивалент.

Не выход . оператор regex.

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

Не привязывая regexp на конце строки

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

Отъезд $f неупомянутый

Отъезд закрывшего кавычки расширения является split+glob оператором. Там, Вы не хотите ни одного, таким образом, $f должен быть заключен в кавычки ("$f").

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

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

Использовать printf вместо этого.

Так лучшее решение:

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

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

9
27.01.2020, 20:45
  • 1
    Хорошо, довольно много вещей, которые я должен улучшить. Но получить его прямо. Цикл не перестал работать по сути. grep действительно работал, но из-за * добавленный ls -F переменная f в $f был расширен. Так или остановите расширение или удалите F флаг от ls команда. Противоположная команда, т.е. без v флаг в grep, действительно работал, потому что не было ничего для расширения соответствия имени файла <filename>.bat* кому. –  mike 27.08.2013, 12:05
  • 2
    @mike, нет, подстановочные знаки (как добавлено ls -F) был подробно остановлен замена команды ($(...)). Если был названный файл scala*, тот подстановочный знак был бы также расширен после расширения $f (и Вы имели замеченный все имена файлов, запускающиеся с scala разделенный пробелами на одной строке) –  Stéphane Chazelas 27.08.2013, 12:41
  • 3
    О, конечно. Это имеет полностью смысл, рассматривая вывод отладки. –  mike 27.08.2013, 12:46

Вы не должны использовать ls проанализировать регистрирует этот путь.

Сначала набор extglob globstar shopt -s extglob globstar затем

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

Используя find

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

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

8
27.01.2020, 20:45
  • 1
    я добираюсь bash: !: event not found . Почему я не должен использовать ls таким образом? –  mike 26.08.2013, 18:41
  • 2
    , потому что Вы не включили extglob Посмотрите выше. –  Valentin Bajrami 26.08.2013, 18:42
  • 3
    Спасибо! И для completness: не нужно использовать ls в для цикла путем я сделал это, потому что некоторые имена файлов могли содержать символы новой строки. –  mike 26.08.2013, 18:46
  • 4
    Можно даже пропустить цикл полностью и использование printf '%s\n' !(*.bat) (можно сделать то же с rm) –  evilsoup 26.08.2013, 19:05
  • 5
    Это не было о печати. Я хотел динамично создать символьные ссылки на scala файлы. Я предполагаю, что это также возможно с find и exec, но цикличное выполнение было легче для меня; D –  mike 26.08.2013, 19:08

Нет ничего по сути неправильно с Вашим для цикла:

$ 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 Wiki для других потенциальных проблем при сценариях вещей в 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, таким образом, у меня нет метода для доказательства этой гипотезы.

1
27.01.2020, 20:45
  • 1
    я добавил отладочные данные к вопросу. Одинарные кавычки ничего не изменили. Пробелы находятся в пути, но я делаю локальную операцию здесь. Имена файлов без пробелов, я не думаю, что это - проблема. –  mike 26.08.2013, 19:39
  • 2
    @slm, я должен не согласиться относительно ls используйте в for контекст цикла.ls просто разработан для человеческого глаза. Другой синтаксический анализ операционных систем ls вывод по-другому. –  Valentin Bajrami 26.08.2013, 19:57
  • 3
    @val0x00ff - на технических достоинствах I 100% соглашаются с Вами, но при выполнении один от сценариев, я сделал эту точную вещь и никогда не имел проблем. Пока Вы понимаете последствия как оператор, он не имеет значения. Просто мои 0,02$. Если сценарий будет только когда-либо выходить в свет в единой системе, различных реализациях ls не имеет значения также. –  slm♦ 26.08.2013, 19:59
  • 4
    Вы пропускаете то, что globbing выполняется на замену команды, так как это не было отключено и что ls был искажен к ls -F. –  Stéphane Chazelas 26.08.2013, 22:53
  • 5
    @StephaneChazelas - я не сомневаюсь, что Вы правы, но я никогда не схватывал тонкость ins/outs того, что продолжается здесь. Если я загружаю ls -F к моему примеру это все еще работает. Я не понимаю Ваш комментарий о globbing, выполняемом на замену команды. Я подозреваю, что другие также пропускают эти детали и следовательно почему, кажется, видят это семейство вопросов так часто здесь. Канонический ответ определенно необходим по этой теме (Вы в значительной степени запустили один с Вашего к этому Q). –  slm♦ 27.08.2013, 00:05

Теги

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