Сценарий оболочки для переименования нескольких файлов из имени их родительских папок - PullRequest
2 голосов
/ 01 февраля 2011

У меня есть такая файловая структура:

  • 00000010
    • 000000001.file1
    • 000000001.file2
  • 00000020
    • 00000003.file1
    • 00000003.file2
    • 00000003.file3
  • ...

Таким образом, существуют папки с 8-значными именами, содержащими один или несколько файлов с именами, начинающимися с 8-значных чисел.Но эти имена файлов - скажем так - не синхронизированы.Поэтому теперь я пытаюсь рекурсивно переименовать их в bash в архив:

  • 00000010
    • 000000010.file1
    • 000000010.file2
  • 00000020
    • 00000020.file1
    • 00000020.file2
    • 00000020.file3
  • ...

Мой скрипт выглядит следующим образом:

#! /bin/bash

find * -maxdepth 1 -name "*" -type d | while read -r dir
do
        rename 's/$dir\/[0-9]{8}/$dir/' *
done

Но это не работает и выдает такие ошибки, как

Глобальному символу "$ dir" требуется явное имя пакета в (eval 1) строка 1.

Как я могу написать это, чтобы переименовать файлы в соответствии с именами их папок?

Спасибо за помощь!

Ответы [ 3 ]

5 голосов
/ 01 февраля 2011

Используйте " вместо ' в rename

Вы должны запустить rename для файлов внутри $dir, поэтому аргумент rename должен быть $dir/* ине просто *

Так как вы хотите заменить dir/8digits на dir/dir, заменяющая часть регулярного выражения должна быть $dir\/$dir

С вышеуказанными изменениями команда выглядит так:1018 *

rename "s/$dir\/[0-9]{8}/$dir\/$dir/" $dir/*
4 голосов
/ 01 февраля 2011

rename на самом деле является сценарием Perl.

Вот как вы можете сделать это, используя только bash и mv:

#!/bin/bash

for dir in *; do
    if test -d "$dir"; then
        (
            cd $dir
            for file in *; do
                newfile=$dir.${file#*.}
                mv "$file" "$newfile"
            done
        )
    fi
done

Сначала скрипт для воспроизведения дерева каталогов:

$ i=1
$ for dir in 000000{1..2}0; do
mkdir $dir
touch $dir/0000000$i.file{1..3}
i=$((i+1))
done
$ find .
.
./00000010
./00000010/00000001.file1
./00000010/00000001.file2
./00000010/00000001.file3
./00000020
./00000020/00000002.file3
./00000020/00000002.file2
./00000020/00000002.file1

А теперь показывает работающий скрипт:

$ ../ren.sh
$ find .
.
./00000010
./00000010/00000010.file1
./00000010/00000010.file2
./00000010/00000010.file3
./00000020
./00000020/00000020.file1
./00000020/00000020.file2
./00000020/00000020.file3
1 голос
/ 01 февраля 2011

Во-первых, * в вашей команде поиска неуместен - вам нужно указать каталог, чтобы начать поиск. . обычно.

Во-вторых, $dir в вашей команде perl rename не будет расширяться оболочкой, поскольку вся строка заключена в кавычки.

В-третьих, *, который вы передаете своей команде perl rename, расширится до всех каталогов и файлов в вашем текущем рабочем каталоге, что, вероятно, не соответствует вашим ожиданиям.

@ Ответ Микеля гораздо приятнее, чем то, над чем я работал, но я подумал, что это все еще может быть полезно. :)

...