내 디렉토리에 "bar_foo.txt"라는 파일이 많이 있는데 이름을 "foo_bar.txt"로 바꾸고 싶습니다.
에서 정규 표현식은 교체의 역참조 검색과 유사 sed
합니다 .vim
's/\(bar\)_\(foo\)/\2_\1/g'
이를 수행할 수 있는 방법이 있습니까
rename
? 파이프ls
로 연결할 수 있는 몇 가지 해킹을 본 적이 있지만 분명히 놀라운 접근 방식sed
은bash
아닙니다.이를 수행할 수 있는 다른 도구가 있습니까?
정규식의 "sed 및 vim 스타일"에 이름이 있습니까?
답변1
rename
Perl 정규식 구현을 사용하는 경우 (예: Debian/Ubuntu/... 또는 prename
Arch Linux) $1
또한 \1
대괄호는 백슬래시 없이 캡처됩니다.
rename 's/(.*)_(.*)/$2_$1/' *_*
그렇지 않다면 직접 구현해야 합니다.
#! /bin/bash
for file in *_* ; do
left=${file%_*}
right=${file##*_}
mv "$file" "$right"_"$left"
done
a_b_c
참고: 작성된 대로 두 명령의 이름이 로 바뀌었습니다 c_a_b
. get 을 수행하려면 b_c_a
첫 번째 캡처 그룹을 .*?
(첫 번째 경우)로 변경하거나 두 번째 경우 첫 번째 캡처 그룹을 %
및 %%
로 변경합니다 ##
.#
답변2
이를 수행하기 위한 표준 도구는 다음과 같습니다 pax
. 하지만 직접 이동하는 것보다 하드 링크와 복사본을 사용하는 것이 더 잘 작동합니다. 물론 모든 작업은 기본적으로 새 링크를 생성하고 이전 링크를 삭제합니다.
나는 단계에서 벗어나는 것을 선호합니다. 지금은 비교하고 대조할 동일한 트리의 복사본 두 개가 있습니다. 이는 파일 이름을 동적으로 바꿀 때 특히 중요합니다. 파일 이름에 대한 편집 작업의 결과는 기존 링크 이름과 동일할 수 있습니다. 이 경우 어떤 파일이 해당 이름을 갖게 됩니까?
따라서 POSIXly로 수행하려면 다음을 수행합니다.
pax -rwls'|^\(bar\)_\(foo\).txt$|\2_\1.txt|' -s'|.*||' *_*.txt .
완료되면 관련 파일에 대한 개별 링크가 생성됩니다. 결과가 요구사항과 일치하는지 확인하고 이전 결과를 삭제하십시오.
또한 정규식 스타일이 표준입니다 sed
.vim
갈아 바수다
답변3
와 함께유틸리티Linux
rename
, 아니요, 이것은 기본적인 문자열 교체만 수행합니다. Perl 기반의 경우rename
예, 다음을 참조하세요.조 로바의 답변.zsh 사용
zmv
:autoload -U zmv # put this in your ~/.zshrc zmv '(*)_(*).(*)' '${2}_$1.$3' zmv -w '*_*.*' '${2}_$1.$3'
위의 두 호출은
zmv
동일합니다. 하위 디렉터리에서 작업을 수행하려면 다음을 사용할 수 있습니다.zmv -w '**/*_*.*' '$1/${3}_$2.$4'
Vi(m) 및 sed(확장) 사용기본 정규식. 당신은 또한 볼 수 있습니다내 정규 표현식이 X에서는 작동하지만 Y에서는 작동하지 않는 이유는 무엇입니까?