Если я правильно понимаю, вы хотите переместить файлы из текущего каталога и его подкаталогов рекурсивно в другой каталог, но только если команда файл
сообщает о них как о файлах «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
, который печатает стандартизованные строки.
Вы можете использовать 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-е поле" может быть неверным...)
Так как это bash, вы можете:
< <(shopt -s extdebug; declare -F my_bash_func) IFS=' ' read -d '' _ _ fn
echo "$fn"
Это сбросит значение extdebug при выходе из подоболочки.
Это будет работать с файлами с пробелами и новой строки.