5

У меня есть каталог, в котором есть файлы со случайными именами. Что я хочу сделать, это переименовать файлы с file1, file2 и так далее.Лексикографически меньшее имя файла должно быть пронумеровано меньшим номером. Как я могу это сделать?

4 ответа4

8

Простой скрипт bash должен это сделать.

#!/usr/bin/env bash

count=0
for i in *; do
    mv "${i}" file${count}.`echo "${i}" | awk -F. '{print $2}'`
    ((++count))
done

Чтобы помочь с построчным объяснением:

  1. Расположение оболочки bash, в которой он выполняется, определяется вашей переменной среды.
  2. Установите переменную count в 0
  3. Создает цикл for, перебирая вывод команды ls (по умолчанию отсортирован по алфавиту).
  4. Перемещает (т.е. переименовывает) файл "i" (текущий в цикле) в file#.ext . «#» - это текущее число в "count" и материал после «.» это быстрый способ получить текущее расширение файла (так что это может работать в папке с различными расширениями файлов).
  5. Увеличить переменную счетчика

петля, петля, петля

  1. сделанный!

Примечание:

  1. Это выполняется в любом каталоге, из которого вы его выполняете. Поэтому в качестве сценария вы хотите добавить аргумент командной строки. Вместо этого я бы открыл терминал, переместился в каталог, чтобы сделать это, и выполнил следующее (точно):

    for i in *; do mv "${i}" "file${count}".`echo "${i}" | 
      awk -F. '{print $2}'`; ((++count)); done
    
  2. Это предполагает, что у вас есть только имена файлов, такие как «file.txt», а не «this.is.a.file.txt»

3

Вы можете использовать этот скрипт 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))
2

Возможность (аналогично решению nerdwaller, но без подоболочек и разветвлений в ):

#!/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), вам не нужен , все это можно сделать в :

#!/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##*.}"

Предостережения

  • Поскольку для этого используется глобализация , это может быть довольно медленным, если в вашем каталоге огромное количество файлов (глобализация может занять некоторое время).
  • Это переименует все, включая каталоги, но не скрытые файлы.

Лечит

  • У меня нет никаких решений относительно скорости в случае огромного количества файлов в .
  • Если вам нужно удалить каталоги из этой процедуры переименования и переименовать только файлы, добавьте [[ -f $i ]] || continue сразу после for i in *; do заявление.
  • Если вам нужно также переименовать скрытые файлы, добавьте shopt -s dotglob сразу после shopt -s nullglob .

Если вы прочитаете здесь, я думаю, вы сможете создать что-то, что соответствует вашим собственным потребностям, из примеров, которые я вам дал, надеюсь, используя хорошую практику (при условии, что вы решите свою проблему, используя конечно).

1

Я хотел реализовать то же самое, когда был студентом и изучал сценарии оболочки Linux. тогда я создал скрипт ниже Посмотри.. https://github.com/rushyang/GTU-OS-Bash-Scripts/blob/master/Working/System%20Scripts/final_rename_updated.sh

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .