Разобрать 3-ю запись в результате объявления

Если я правильно понимаю, вы хотите переместить файлы из текущего каталога и его подкаталогов рекурсивно в другой каталог, но только если команда файл сообщает о них как о файлах «Microsoft Word». То есть вас интересуют файлы, для которых file "$ filename" | grep 'Microsoft Word' производит некоторый вывод.

Самый простой способ - это спокойно относиться к делу и рассуждать последовательно. Если вам нужны файлы только в текущем каталоге, вы можете использовать цикл для и шаблон подстановки:

for f in *.doc; do
  if …
done

Какое условие? Мы хотим проверить, появляется ли Microsoft Word в выводе файла «$ f» . Я использую файл - для защиты от файлов, имена которых начинаются с - .

for f in *.doc; do
  if file -- "$f" | grep -s 'Microsoft Word'; then
    …
  fi
done

Все, что нам нужно сделать, это добавить команду для перемещения файлов.

for f in *.doc; do
  if file -- "$f" | grep -s 'Microsoft Word'; then
    mv -- "$f" ../NewDirectory/
  fi
done

Если вы хотите также искать файлы в подкаталогах, используйте шаблон ** Wilcdard для рекурсивного подстановки. В bash его нужно активировать с помощью shopt -s globstar (в ksh93 вам нужно установить -o globstar , а в zsh он работает из коробки; в других оболочках этого нет характерная черта). Помните, что bash ≤4.2 следует за символическими ссылками на каталоги.

for f in **/*.doc; do
  if file -- "$f" | grep -s 'Microsoft Word'; then
    mv -- "$f" ../NewDirectory/
  fi
done

Обратите внимание, что все перемещенные файлы заканчиваются на ../ NewDirectory / , подкаталоги не создаются. Если вы хотите воспроизвести дерево каталогов, вы можете использовать конструкции обработки строк для извлечения части каталога из имени файла и mkdir -p для создания целевого каталога, если это необходимо.

for f in ./**/*.doc; do
  if file "$f" | grep -s 'Microsoft Word'; then
    d="${f%/*}"
    mkdir -p ../NewDirectory/"$d"
    mv "$f" ../NewDirectory/"$d"
  fi
done

Вместо синтаксического анализа вывода файла , который несколько хрупок, вы можете предпочесть синтаксический анализ file -i , который печатает стандартизованные строки.

0
02.05.2018, 08:21
2 ответа

Вы можете использовать awkдля этого:

file=$(declare -F my_bash_func | awk '{print $3}')

Или используйте встроенные в bash -ins, прочитайте их в массив:

func_info=( $(declare -F my_bash_func) )
file=${func_info[2]}
line_number=${func_info[1]}

Но имейте в виду, что вывод declare -F my_bash_funcне очень удобен для синтаксических анализаторов... Если файл, содержащий функцию, получен по относительному пути, вывод extdebugпросто напечатает относительный путь (, даже если вы re больше не в этом каталоге. )Кроме того, если в пути есть пробелы или непечатаемые символы, они будут сохранены в выводе (, так что "3-е поле" может быть неверным...)

0
28.01.2020, 04:24

Так как это bash, вы можете:

< <(shopt -s extdebug; declare -F my_bash_func) IFS=' ' read -d '' _ _ fn
echo "$fn"

Это сбросит значение extdebug при выходе из подоболочки.
Это будет работать с файлами с пробелами и новой строки.

0
28.01.2020, 04:24

Теги

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