2015-02-19 2 views
0

Буква Word & Документы Excel перемещались на сервере, когда процесс завершался до его завершения. В результате у нас осталось несколько прекрасных файлов с расширением .tmp, и нам нужно переименовать эти файлы обратно в соответствующее расширение .xlsx или .docx.Bash - Рекурсивно переименовывать файлы «.tmp»

Вот мой текущий код, чтобы сделать это в Bash:

#!/bin/sh 

for i in "$(find . -type f -name *.tmp)"; do 
    ft="$(file "$i")" 
    case "$(file "$i")" in 
     "$i: Microsoft Word 2007+") 
      mv "$i" "${i%.tmp}.docx" 
      ;; 
     "$i: Microsoft Excel 2007+") 
      mv "$i" "${i%.tmp}.xlsx" 
      ;; 
    esac 
done 

кажется, что в то время как это делает поиск рекурсивно, это делает только 1 файл. Если он находит начальное совпадение, он не переходит к переименованию остальных файлов. Как я могу получить это для правильной петли через каталоги рекурсивно, если он не делает всего 1 файл за раз?

+1

Не используйте 'find' таким образом. См. [ParsingLs] (http://mywiki.wooledge.org/ParsingLs) для подробного объяснения причин. – ghoti

ответ

1

я тоже рекомендовал бы использовать find. Я хотел бы сделать это в два прохода find:

find . -type f -name \*.tmp \ 
-exec sh -c 'file "{}" | grep -q "Microsoft Word 2007"' \; \ 
-exec sh -c 'f="{}"; echo mv "$f" "${f%.tmp}.docx"' \; 

find . -type f -name \*.tmp \ 
-exec sh -c 'file "{}" | grep -q "Microsoft Excel 2007"' \; \ 
-exec sh -c 'f="{}"; echo mv "$f" "${f%.tmp}.xlsx"' \; 

Линии для удобства чтения.

Каждый экземпляр find будет искать файлы tmp, а затем использовать -exec для проверки вывода find. Это похоже на то, как вы делаете это в цикле while в своем сценарии оболочки, только он запускается с самого find. Мы используем трубу до grep вместо вашего оператора case.

Второй -exec запускается только в том случае, если первый вернул «истинный» (то есть grep -q ... что-то нашел) и выполняет переименование в крошечном экземпляре оболочки.

Я не профилировал это, чтобы узнать, будет ли он быстрее или медленнее, чем цикл в сценарии оболочки. Еще один способ справиться с вещами.

+1

'{}' не должен использоваться таким образом. Он позволяет произвольно вводить код. Вместо этого используйте его как: '-exec sh -c '... do stuff с« $ 0 »...' {} \;'. Таким образом, он будет полностью защищен (поймите: вот так, вы не смешиваете код и данные). –

2

Попробуйте find команды:

while IFS= read -r -d '' i; do 
    ft="$(file "$i")" 
    case "$ft" in 
     "$i: Microsoft Word 2007+") 
      mv "$i" "${i%.tmp}.docx" 
      ;; 
     "$i: Microsoft Excel 2007+") 
      mv "$i" "${i%.tmp}.xlsx" 
      ;; 
    esac 
done < <(find . -type f -name '*.tmp' -print0) 
  • Использование <(...) называется подменой процесса запуска find команды здесь
  • Quote
  • шаблон файла в find
  • Использования -print0 получить find вывод, разграниченного нулевой символ, чтобы символы пробела/новой строки в именах файлов
  • Использование IFS= и -d '' читать нуль отделенных имен файлов
Смежные вопросы