У меня есть каталог, в котором есть файлы со случайными именами. Что я хочу сделать, это переименовать файлы с file1, file2 и так далее.Лексикографически меньшее имя файла должно быть пронумеровано меньшим номером. Как я могу это сделать?
4 ответа
Простой скрипт bash должен это сделать.
#!/usr/bin/env bash
count=0
for i in *; do
mv "${i}" file${count}.`echo "${i}" | awk -F. '{print $2}'`
((++count))
done
Чтобы помочь с построчным объяснением:
- Расположение оболочки bash, в которой он выполняется, определяется вашей переменной среды.
- Установите переменную count в 0
- Создает цикл for, перебирая вывод команды
ls
(по умолчанию отсортирован по алфавиту). - Перемещает (т.е. переименовывает) файл "i" (текущий в цикле) в
file#.ext
. «#» - это текущее число в "count" и материал после «.» это быстрый способ получить текущее расширение файла (так что это может работать в папке с различными расширениями файлов). - Увеличить переменную счетчика
петля, петля, петля
- сделанный!
Примечание:
Это выполняется в любом каталоге, из которого вы его выполняете. Поэтому в качестве сценария вы хотите добавить аргумент командной строки. Вместо этого я бы открыл терминал, переместился в каталог, чтобы сделать это, и выполнил следующее (точно):
for i in *; do mv "${i}" "file${count}".`echo "${i}" | awk -F. '{print $2}'`; ((++count)); done
Это предполагает, что у вас есть только имена файлов, такие как «file.txt», а не «this.is.a.file.txt»
Вы можете использовать этот скрипт Python:
#!/usr/bin/python
import os
#enter the path to the folder: relative or absolute
direc = raw_input('Enter the path to directory: ')
os.chdir(os.path.join(os.getcwd(),direc))
files = os.listdir('.')
def func(x):
return map(str.lower,os.path.splitext(x))
files.sort(key = func)
for i,x in enumerate(files, 1):
name, ext = os.path.splitext(x)
os.rename(x, 'file{}{}'.format(i,ext))
Возможность bash (аналогично решению nerdwaller, но без подоболочек и разветвлений в awk):
#!/usr/bin/bash
shopt -s nullglob
count=0
for i in *; do
mv -nv -- "$i" "file$((++count))"
done
Переключатели для mv
:
-n
без клоббера: не перезаписывает существующий файл. Удалите его, если вы действительно хотите перезаписать файлы (может быть недоступно в зависимости от вашей версииmv
),-v
для многословия: расскажите, что он делает. Весьма необязательно (но мне нравится, когда эти строки на моем терминале производят впечатление на моих коллег),--
для конца опций: без этого, и если имя файла начинается с дефиса, это запутаетmv
поскольку он попытается интерпретировать его как опцию. Может быть недоступно в зависимости от вашей версииmv
. Используйте его, если доступно!
Я также использую необязательное поведение оболочки nullglob
чтобы при отсутствии файлов ошибки не возникали (цикл не будет выполнен, так как *
в этом случае расширится до нуля).
Если вам тоже нужно обрабатывать расширения (как в версии nerdwaller), вам не нужен awk, все это можно сделать в bash:
#!/usr/bin/bash
shopt -s nullglob
count=0
for i in *; do
mv -nv -- "$i" "file$((++count)).${i##*.}"
done
Обратите внимание, что нумерация не будет иметь начальных нулей, поэтому вы получите файлы с именем так:
file1
file2
...
file10
file11
...
и это может испортить порядок файлов в списках. Если вам нужны также ведущие нули:
#!/usr/bin/bash
shopt -s nullglob
files=( * )
lz=0
for ((n=${#files[@]};n;n/=10)); do ((++lz)); done
count=0
for i in "${files[@]}"; do
printf -v n "%0${lz}d" $((++count))
mv -nv -- "$i" "file$n"
done
И если вы хотите сохранить оригинальное расширение файла, замените строку
mv -nv -- "$i" "file$n"
с
mv -nv -- "$i" "file$n.${i##*.}"
Предостережения
- Поскольку для этого используется глобализация bash , это может быть довольно медленным, если в вашем каталоге огромное количество файлов (глобализация может занять некоторое время).
- Это переименует все, включая каталоги, но не скрытые файлы.
Лечит
- У меня нет никаких решений относительно скорости в случае огромного количества файлов в bash.
- Если вам нужно удалить каталоги из этой процедуры переименования и переименовать только файлы, добавьте
[[ -f $i ]] || continue
сразу послеfor i in *; do
заявление. - Если вам нужно также переименовать скрытые файлы, добавьте
shopt -s dotglob
сразу послеshopt -s nullglob
.
Если вы прочитаете здесь, я думаю, вы сможете создать что-то, что соответствует вашим собственным потребностям, из примеров, которые я вам дал, надеюсь, используя хорошую практику bash (при условии, что вы решите свою проблему, используя bash, конечно).
Я хотел реализовать то же самое, когда был студентом и изучал сценарии оболочки Linux. тогда я создал скрипт ниже Посмотри.. https://github.com/rushyang/GTU-OS-Bash-Scripts/blob/master/Working/System%20Scripts/final_rename_updated.sh