#bash #shell
#bash #оболочка
Вопрос:
Я должен переименовать некоторые файлы, которые я точно не знаю, где они находятся, и сохранить их расширения.
Пример: файловая система-2.1.3.war, system-2.1.3.ear, system-2.1.3.ejb в system.ear, system.war, system.ejb
Итак, я написал это.
find /DIR1 -name "*.ear" -o -name "*.war" -o -name "*.ejb"
-exec bash -c 'export var1={}; cp $var1 NEW_NAME${var1: -4}' ;
Проблема в том, что это работает только для последнего файла в списке «или» команды «найти». Итак, если файл system-2.1.3.ejb, работает, для system-2.1.3.war и system-2.1.3.ear — нет.
Если я изменю find на
find /DIR1 -name "*.ejb" -o -name "*.war" -o -name "*.ear"
Обратите внимание, что *.ear теперь является последним, он будет работать для system-2.1.3.ear, а не для остальных и так далее.
Пожалуйста, помогите мне это исправить.
Я знаю, что могу создать скрипт для выполнения этого, но мне нужен код «в одну строку».
Ответ №1:
Вместо того, чтобы встраивать {}
в скрипт, передайте его в качестве аргумента:
find /DIR1 ( -name "*.ear" -o -name "*.war" -o -name "*.ejb" )
-exec sh -c 'ext=${1##*.}; cp "$1" "NEW_NAME.$ext"' _ '{}' ;
Без (...)
группировки, -exec
применяется только к основному, с которым оно неявно «и»отредактировано, предыдущему.
Вы также можете ограничить количество вызовов командной оболочки, перебирая несколько аргументов:
find /DIR1 ( ... ) -exec sh -c 'for f; do ext=${f##*.}; cp "$f" "NEW_NAME.$ext"; done' _ {}
Комментарии:
1. Я добавляю (an) в свой код и работает, спасибо. Но зачем вы используете «_ ‘{}'», если cp «$ 1» «NEW_NAME.$ ext» уже выполняет эту работу?
2. Аргумент для
-c
— это скрипт для выполнения, но вам все равно нужно передать аргументы для$1
расширения до. Это упрощает проверку правильности кавычек любых аргументов, передаваемыхcp
.
Ответ №2:
попробуйте это;
find /DIR1 ( -name "*.ear" -o -name "*.war" -o -name "*.ejb" ) -exec bash -c 'export var1={}; cp $var1 NEW_NAME${var1: -4}' ;
или
find ./DIR1/ -regex '.*(.ear|.war|.ejb)$' -exec bash -c 'export var1={}; cp $var1 NEW_NAME${var1: -4}' ;
Например;
user@host $ ls -arlt DIR1/
total 76
-rw-rw-r-- 1 user user 0 Oct 21 22:59 system-2.1.3.war
-rw-rw-r-- 1 user user 0 Oct 21 22:59 system-2.1.3.ear
-rw-rw-r-- 1 user user 0 Oct 21 22:59 system-2.1.3.ejb
drwxrwxr-x 2 user user 4096 Oct 21 22:59 .
user@host $ find . ( -name "*.ear" -o -name "*.war" -o -name "*.ejb" ) -exec bash -c 'export var1={}; cp $var1 NEW_NAME${var1: -4}' ;
user@host $ ls -ralt
total 76
-rw-rw-r-- 1 user user 0 Oct 21 22:59 system-2.1.3.war
-rw-rw-r-- 1 user user 0 Oct 21 22:59 system-2.1.3.ear
-rw-rw-r-- 1 user user 0 Oct 21 22:59 system-2.1.3.ejb
drwxrwxrwt 11 root root 69632 Oct 21 23:10 ..
-rw-rw-r-- 1 user user 0 Oct 21 23:10 NEW_NAME.war
-rw-rw-r-- 1 user user 0 Oct 21 23:10 NEW_NAME.ear
-rw-rw-r-- 1 user user 0 Oct 21 23:10 NEW_NAME.ejb
drwxrwxr-x 2 user user 4096 Oct 21 23:10 .
Ответ №3:
Если у вас есть rename
утилита, то вы можете избежать разветвления подпроцесса BASH для каждого файла, а также использовать функцию регулярных выражений в, find
чтобы избежать множества -name
опций:
find /DIR1 -regextype awk -regex '.*.([we]ar|ejb)$'
-exec rename 's/.*(.[^.] )$/system$1/' '{}'
Ответ №4:
Я бы использовал while
:
find . -name "*.war" -o -name "*.ejb" -o -name "*.ear" | while read file; do cp $file NEW_NAME${file: -4}; done
Имейте в виду, что и этот, и ваш пример копируют файлы в текущий каталог, поэтому, если у вас в дереве более одного *.war
, *.ejb
или *.ear
, в целевом каталоге останется только последний (ы).