Скрипт Linux для добавления лидирующих нулей к именам файлов - PullRequest
52 голосов
/ 09 сентября 2010

У меня есть папка с 1700 файлами.Все они названы как 1.txt или 1497.txt и т. Д. Я хотел бы переименовать все файлы так, чтобы все имена файлов были длиной в четыре цифры.

Т.е. 23.txt становится 0023.txt.

Что такое сценарий оболочки, который будет делать это?Или связанный с этим вопрос: как использовать grep для сопоставления только строк, которые содержат \d.txt (то есть одну цифру, затем точку, затем буквы txt)?

Вот что у меня так далеко:

for a in [command i need help with]
do
  mv $a 000$a
done

В основном, запустите это три раза с командами, чтобы найти однозначное, двухзначное и трехзначное имя файла (с измененным числом начальных нулей).

Ответы [ 9 ]

47 голосов
/ 09 сентября 2010

Попробуйте:

for a in [0-9]*.txt; do
    mv $a `printf %04d.%s ${a%.*} ${a##*.}`
done

При необходимости измените шаблон имени файла ([0-9]*.txt).


Переименованное переименование общего назначения, которое не делает никаких предположений о начальном наборе имен файлов:

X=1;
for i in *.txt; do
  mv $i $(printf %04d.%s ${X%.*} ${i##*.})
  let X="$X+1"
done

По той же теме:

14 голосов
/ 09 сентября 2010

Используя сценарий rename (* в некоторых случаях prename), который иногда устанавливается вместе с Perl, вы можете использовать выражения Perl для переименования.Сценарий пропускает переименование в случае конфликта имен.

Команда ниже переименовывает только те файлы, которые имеют четыре или менее цифр, за которыми следует расширение «.txt».Он не переименовывает файлы, которые строго не соответствуют этому шаблону.Он не усекает имена, состоящие из более чем четырех цифр.

rename 'unless (/0+[0-9]{4}.txt/) {s/^([0-9]{1,3}\.txt)$/000$1/g;s/0*([0-9]{4}\..*)/$1/}' *

Несколько примеров:

Original    Becomes
1.txt       0001.txt
02.txt      0002.txt
123.txt     0123.txt
00000.txt   00000.txt
1.23.txt    1.23.txt

Другие ответы, приведенные до сих пор, будут пытаться переименовать файлы, которые не соответствуютк шаблону, выдают ошибки для имен файлов, которые содержат нецифровые символы, выполняют переименования, которые вызывают конфликты имен, пытаются и не удается переименовать файлы с пробелами в их именах и, возможно, другие проблемы.

12 голосов
/ 09 сентября 2010
for a in *.txt; do
  b=$(printf %04d.txt ${a%.txt})
  if [ $a != $b ]; then
    mv $a $b
  fi
done
9 голосов
/ 09 сентября 2010

Однострочный:

ls | awk '/^([0-9]+)\.txt$/ { printf("%s %04d.txt\n", $0, $1) }' | xargs -n2 mv

Как использовать grep для сопоставления только строк, содержащих \ d.txt (IE 1 цифра, затем точка, затем буквы txt)?

grep -E '^[0-9]\.txt$'
4 голосов
/ 03 января 2013

Предположим, у вас есть файлы с типом данных .dat в вашей папке.Просто скопируйте этот код в файл с именем run.sh, сделайте его исполняемым, запустив chmode +x run.sh, а затем выполните команду ./run.sh:

#!/bin/bash
num=0
for i in *.dat
do

  a=`printf "%05d" $num`
  mv "$i" "filename_$a.dat"
  let "num = $(($num + 1))"
done

. Все файлы в вашей папке будут преобразованы в filename_00000.dat,filename_00001.dat и т. Д.

1 голос
/ 16 марта 2016

Эта версия также поддерживает обработку строк до (после) числа.Но в основном вы можете выполнить любое сопоставление регулярных выражений + printf, если ваш awk поддерживает это.Кроме того, он поддерживает пробельные символы (кроме символов новой строки) в именах файлов.

for f in *.txt ;do
    mv "$f" "$( 
        awk -v f="$f" '{
            if ( match(f, /^([a-zA-Z_-]*)([0-9]+)(\..+)/, a)) {
                printf("%s%04d%s", a[1], a[2], a[3])
            } else {
                print(f)
            }
        }' <<<''
    )"
done
0 голосов
/ 28 октября 2017

Чтобы предоставить решение, которое тщательно написано, чтобы оно было правильным даже при наличии имен файлов с пробелами:

#!/usr/bin/env bash

pattern='%04d'  # pad with four digits: change this to taste

# enable extglob syntax: +([[:digit:]]) means "one or more digits"
# enable the nullglob flag: If no matches exist, a glob returns nothing (not itself).
shopt -s extglob nullglob

for f in [[:digit:]]*; do               # iterate over filenames that start with digits
  suffix=${f##+([[:digit:]])}           # find the suffix (everything after the last digit)
  number=${f%"$suffix"}                 # find the number (everything before the suffix)
  printf -v new "$pattern" "$number" "$suffix"  # pad the number, then append the suffix
  if [[ $f != "$new" ]]; then                   # if the result differs from the old name
    mv -- "$f" "$new"                           # ...then rename the file.
  fi
done
0 голосов
/ 21 января 2014

Однострочная подсказка:

while [ -f ./result/result`printf "%03d" $a`.txt ]; do a=$((a+1));done
RESULT=result/result`printf "%03d" $a`.txt
0 голосов
/ 09 сентября 2010

Чтобы соответствовать только однозначным текстовым файлам, вы можете сделать ...

$ ls | grep '[0-9]\.txt'
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...