Intereting Posts
Как узнать, работает ли crontab? Черный экран CentOS 7, VirtualBox-5.1.10 Выполнить команду над каталогами с рекурсивным именем Монитор неизвестных и двух мониторов Debian Как мне получить ~ / .bashrc для выполнения всех скриптов в каталоге ~ / Shell с помощью цикла? Объединение нескольких файлов с одинаковым заголовком Как заставить startx открывать новую сессию X в tty7 на малине Pi? Измените известные слова 1 и 3 строки, сохраняя неизменное слово 2 постоянным Не удается отформатировать Samsung SD-карту Android-Meta Почему страница U / Down, Home / End не работает на Solaris поверх ssh от Ubuntu? Регулярное выражение Perl для распознавания нескольких строк sed: -e выражение # 1, char 44: регулярное выражение с неопределенным адресом Восстановить загрузочный раздел EFI Сравнить деревья каталогов относительно имени файла (и размера и даты) Выполнять удаленные команды, полностью отсоединяясь от ssh-соединения

переменные в команде find и проблема с оболочкой

Возможный дубликат:
Рекурсивные файлы и каталоги переименования

Я написал следующий скрипт:

#!/bin/bash SAVEIFS=$IFS alias export='export' IFS=$(echo -en "\n\b") find $1 -name "*" -a -type f -exec sh -c let len=`expr length {}` \; -exec sh -c let str=`expr substr {} 1 len-3` \; -exec ffmpeg -y -i {} $str.mp3 \; # restore $IFS unalias export IFS=$SAVEIFS 

Проблема:

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

  1. переменные использования

  2. не использовать run shell

Итак, как я это делаю?

При запуске следующего скрипта:

 find $1 -name "*" -a -type f -exec let len=`expr length {}` \; -exec let str=`expr substr {} 1 len-3` \; -exec ffmpeg -y -i {} $str.mp3 \; # Note : above script doesn't has 'sh -c' 

Я получаю следующую ошибку:

 find: `let': No such file or directory 

Я протестировал его с экспортом или удалением экспорта или пусть, я обнаружил, что -exec имеет проблему со встроенной командой оболочки ….!

Есть ли у вас какие-либо идеи????

Вам нужно позаботиться о нескольких вещах

  • двойные кавычки для защиты содержимого переменной от интерпретации оболочки. IFS содержит по умолчанию «space + tab + newline», поэтому: NEWIFS=IFS , вероятно, закончит тем, что ничего не добавит в NEWIFS.

     SAVEIFS="$IFS" ... IFS="$(echo -en "\n\b")" #yes, you can have " inside $( ... ) : the shell will gladly interpret them by # order of depth inside the $() construct. # A big advantage over using backquotes where it would get mixed up and almost unreadable ... IFS="$SAVEIFS" 
  • Не используйте зарезервированные слова в качестве имен переменных (избегайте for let и т. Д. Избегайте также многих «общих» имен переменных, то есть LINES , COLUMNS и т. Д.

    • почему выставлять export на export ? выглядит как хороший способ создать цикл, если оболочка устарела или, в лучшем случае, бесполезна.

    • precising -name * означает, что вы избегаете имени файла или dirnames, начинающихся с . ,

    • -exec sh .... запустит его в подсетей sh : любые переменные, которые вы объявляете там, будут потеряны после того, как sh выйдет из вызывающей оболочки.

Вам нужно что-то вроде:

 #!/bin/bash for adirectory in "$@" ; do find "$adirectory" -type f -name '*.3gp' -print | while IFS= read -r wholeline ; do mylength=$(echo "$wholeline" | wc -c) #Not needed, just kept as exemple of a way to achieve it myfilewithoutext="$(echo "$wholeline" | sed -e 's/.3gp$//' )" #keeps only the filename without its ".3gp" or ".3GP" extension. ffmpeg -y -i "$wholeline" "${myfilewithoutext}.mp3" > /dev/null #? please check if it works done #end of the find|while done #end of the for looping on all the arguments passed to the script (dir names) 

IFS в то while IFS= read -r wholeline ; do while IFS= read -r wholeline ; do будет устанавливаться в пустую строку ТОЛЬКО во время вызова read -r wholeline . Нетронутый снаружи. VAR="something" command parameters команды VAR="something" command parameters будут вызывать параметры команды, при этом значение VAR временно устанавливается на something . Здесь мы устанавливаем IFS в '' , т.е. ничего. Он по-прежнему будет передаваться по read wholeline , а поскольку IFS пуст, вся строка заканчивается чтением read wholeline .

Согласно комментарию (преобразование * .3gp в * .mp3):

 for n in *.3gp; do ffmpeg -y -i "$n" "${n%.3gp}.mp3" done 

В соответствии с комментарием оливье, чтобы также работать с файлами в подкаталогах, *.3gp можно заменить на $(find ...) , если имена файлов не нуждаются в экранировании (а именно, они не содержат пробельных символов или символов глобуса \[?* ). В качестве альтернативы можно использовать **/*.3gp (в bash, shopt -s extglob в вашем .bashrc ).