2016-04-27 2 views
3

У меня есть куча файлов, которые просто просто время unix. Проблема в том, что их имена файлов идут в миллис, а программа, которая сканирует каталог, ожидает, что они будут в считанные секунды. Поэтому мне нужно переименовать все файлы, чтобы удалить последние 3 цифры перед расширением .txt. IE:Bash Regex переименовывать файлы

1461758015598.txt -> 1461758015.txt

Я новичок в Regex и Баш, поэтому я не знаю, как это сделать.

+0

A отказоустойчивая альтернатива python, которая работает рекурсивно: http://stackoverflow.com/a/39698169/191246 – ccpizza

ответ

3

Вот один из способов:

for f in *.txt; do 
    mv "$f" "${f/[0-9][0-9][0-9].txt/.txt}" 
done 

Между do и done, он смотрит на один файл в то время, и имя текущего файла находится в f параметра Я. "$f" - значение этого параметра, неизмененное. "${f/[0-9][0-9][0-9].txt/.txt}" - значение параметра с применяемой заменой: замените «три цифры, а затем .txt» всего .txt.

Как отметил @anubhava, если вы запустите его более одного раза, он будет удерживать цифры от имен файлов, поэтому не делайте этого. Вы можете сделать это идемпотентным, ужесточив шаблон шара. Это немного громоздкий:

for f in [0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9].txt; do 
    mv "$f" "${f/[0-9][0-9][0-9].txt/.txt}" 
done 

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

for f in $(ls -1 | egrep '^[0-9]{13}\.txt$'); do 
    mv "$f" "${f/[0-9][0-9][0-9].txt/.txt}" 
done 

Вы можете уменьшить ограничение на просто «никаких новых строк» ​​с помощью while read цикла:

ls -1 | egrep '^[0-9]{13}\.txt$' | while read f; do 
    mv "$f" "${f/[0-9][0-9][0-9].txt/.txt}" 
done 
+4

OP должен запускать его только один раз или он также переименует '1461758015.txt' в' 1461758.txt', а затем '1461758.txt 'to' 1461.txt' – anubhava

+0

Если OP использует bash в любом случае, extglob с 'ls + ([0-9]). txt | egrep ... 'может быть более безопасным, а также более эффективным в действительно больших каталогах. – ghoti

0

ответ Марка охватывает целый ряд вариантов.

Но если вы хотите что-то рекурсивное, я бы с раствором find на основе, как это:

find -E . -regex '.*/[0-9]{13}\.txt' -exec \ 
    sh -c 'set -; mv -v "$0" "${0%???.txt}.txt"' "{}" \; 

Примечания:

  • Я использую FreeBSD, которая имеет -E опцию скажите -regex, чтобы использовать ERE. Если вы используете более старую ОС, вам может потребоваться преобразовать ERE в BRE.
  • ERE настаивает на 13 цифрах. Это избавляет вас от беспокойства anubhava о увеличении уменьшения, если вы запускаете конверсию более одного раза.
  • Для расширения параметров я использую ${..%..} вместо ${../../}, что делает этот POSIX совместимым, а не зависимым от bash. (Разумеется, это тоже будет работать в bash, это просто не нужно.)
  • Вы можете задаться вопросом, почему матч просто разбивает отдельные символы подстановочных знаков вместо цифр. Это хорошо - мне легче набирать, и мы уже установили ограничение имени файла как часть опций на find.

Если вы предпочитаете, чтобы избежать использования find, но все еще хотите что-то рекурсивное в Баш, вы можете использовать globstar вариант:

shopt -s globstar extglob 
for f in **/+([0-9]).txt; do 
    [[ $f =~ ^[0-9]{13}\.txt$ ]] && mv -v "$f" "${f%...\.txt}.txt" 
done 

Обратите внимание, что globstar зависит от Баш версии 4.

Смежные вопросы