Рекурсивно удалить суффикс имени файла из файлов в оболочке

Когда мы разрабатываем локально, мы добавляем «.dev» или «.prod» к файлам, которые должны быть доступны только для сервера разработки/производства соответственно.

Что я хотел бы сделать, это; после развёртывания сайта на сервер рекурсивно найти все файлы с суффиксом ".dev" (например) и удалить его (переименовав файл). Как мне это сделать, желательно полностью в оболочке (без сценариев), чтобы я мог добавить его в наш сценарий развертывания?

На наших серверах установлена ​​Ubuntu 10.04.


person Tom    schedule 05.08.2010    source источник


Ответы (3)


Попробуйте это (не только для оболочки, требуются утилиты find и mv):

find . '(' -name '*.dev' -o -name '*.prod' ')' -type f -execdir sh -c 'mv -- "$0" "${0%.*}"' '{}' ';'

Если у вас есть утилиты rename и xargs, вы можете значительно ускорить это:

find . '(' -name '*.dev' -o -name '*.prod' ')' -type f -print0 | xargs -0 rename 's/\.(dev|prod)$//'

Обе версии должны работать с любым именем файла, включая имена файлов, содержащие символы новой строки.

person Philipp    schedule 05.08.2010
comment
+1, это лучше, чем у меня. Тем не менее, если у вас действительно строгие требования к совместимости, вы, возможно, захотите знать, что POSIX find не имеет -execdir или -print0, и я считаю, что "${0%.dev}" — это ерунда. - person bcat; 05.08.2010
comment
Кажется, это работает хорошо; Я заменил 's/\.dev$/.prod/' на 's/\.dev$//', так как хочу полностью удалить расширение. Особых требований к совместимости нет, поэтому зависимость от rename/xargs не является проблемой. Спасибо! - person Tom; 05.08.2010
comment
Страница руководства sh говорит, что sh знает об удалении суффикса. -execdir можно заменить на -exec (который, по словам руководства Linux, менее безопасен), но -print0 заменить невозможно. - person Philipp; 05.08.2010

Это полностью не проверено, но это должно работать в POSIX-подобной оболочке по вашему выбору:

remove-suffix () {
    local filename
    while read filename; do
        mv "$filename" "$(printf %s "$filename" | sed "s/\\.$1\$//")"
    done
}

find -name '*.dev' | remove-suffix .dev

Примечание. В очень необычном случае, когда одно или несколько имен ваших файлов содержат символ новой строки, это не сработает.

person bcat    schedule 05.08.2010

for file in `ls *.dev`; do echo "Old Name $file"; new_name=`echo $file | sed -e 's/dev//'` ; echo "New Name $new_name"; mv $file $new_name; done

В примере того, что я недавно использовал, этот код ищет любой файл, который заканчивается на new.xml, изменяет дату в имени файла (имена файлов были в форме xmlEventLog_2010-03-23T11:16:16_PFM

for file in `ls *.dev`; do echo "Old Name $file"; new_name=`echo $file | sed -e 's/dev//'` ; echo "New Name $new_name"; mv $file $new_name; done
1.xml), удаляет _new из name и переименовывает имя файла в новое имя:

for file in `ls *new.xml`; do echo "Old Name $file"; new_name=`echo $file | sed -e 's/[0-9]\{4\}-[0-9]\{2\}-[0-9]\{2\}/2010-03-23/g' | sed 's/_new//g'` ; echo "New Name $new_name"; mv $file $new_name; done

Это то, что вы хотели?

person amadain    schedule 05.08.2010
comment
Это не рекурсия в подкаталоги. - person bcat; 05.08.2010
comment
И он не работает с именами файлов, содержащими что-то особенное (пробелы, новые строки, непечатаемые символы...). - person Philipp; 05.08.2010
comment
просто пытаюсь помочь. больше не буду делать это на этом сайте - person amadain; 05.08.2010
comment
Чувак, остынь. Мы пытались помочь вам улучшить ваш ответ, который на самом деле не отвечает на исходный вопрос. Это не личная атака на вас. - person bcat; 05.08.2010
comment
Потому что это неправильно. (И я не минусовал его, чего бы это ни стоило.) - person bcat; 05.08.2010