Обрезать символы до точки, если имя файла имеет префикс в Bash - PullRequest
3 голосов
/ 16 ноября 2009

У меня есть каталог, который выглядит так:

pages/
    folder1/
        folder1.filename1.txt
        folder1.filename2.txt
    folder2/
        folder2.filename4.txt
        folder2.filename5.txt
    folder3/
        filename6.txt

Я хочу, чтобы это выглядело так:

pages/
    folder1/
        filename1.txt
        filename2.txt
    folder2/
        filename3.txt
        filename4.txt
    folder3/
        filename5.txt

С ls * | sed -e s/^[^.]*.// > /tmp/filenames.txt я получаю файл, содержащий:

filename1.txt
filename2.txt
filename3.txt
filename4.txt
txt

Как я могу сказать, что sed игнорирует имена файлов в форме [filename].[suffix] и просматривает только имена файлов в форме [foldername].[filename].[suffix]?

Последний сценарий (как было указано, команда find упростила бы ситуацию, но это сработало):

for folder in $(ls .)
do
    if test -d $folder
    then
        pushd $folder
                ls * | sed 's/.*\.\(.*\..*\)/\1/' > /tmp/filenames.txt
                ls * > /tmp/current.txt

                exec 3</tmp/current.txt
                exec 4</tmp/filenames.txt

                while read file <&3; read name <&4;
                do
                    mv "$file" "$name"
                done

                rm /tmp/current.txt
                rm /tmp/filenames.txt
        popd
    else
        echo $folder "not a directory"
    fi
done

exit 0

Эта страница теперь является вики-сообществом. Ниже вы можете добавить более элегантные решения:

for folder in $(ls .)
do 
     something better

Ответы [ 3 ]

3 голосов
/ 16 ноября 2009

Попробуйте:

sed 's/.*\.\(.*\..*\)/\1/'

Вы действительно должны использовать find, тогда вам не понадобится проверка для "-d folder" или временного файла и execs или цикла while.

Вы можете избежать временного файла, используя подстановку процесса:

while read line
do
    echo $line
done < <(ls)

Еще один интересный момент: в вашей системе уже может быть Perl-скрипт с именем rename или prename, который будет переименовывать файлы с помощью регулярного выражения.

2 голосов
/ 16 ноября 2009

Вам не нужно использовать sed:

ls * > /tmp/current.txt
exec 3</tmp/current.txt
while read file <&3;
do
    replacement=${file#${folder}.}
    if [ "$replacement" != "txt" ] ; then
        mv "$file" "$replacement"
    fi
done
0 голосов
/ 16 ноября 2009

используйте следующее регулярное выражение:

/\A(.\*?\\.){2,2}.+\Z/
...