여러 디렉토리를 살펴보고 _test.rb로 끝나는 모든 파일의 이름을 _spec.rb로 끝내고 싶습니다. bash로하는 방법을 전혀 알아 내지 못했던 것이므로 이번에는 그것을 못 박는 데 약간의 노력을 기울일 것이라고 생각했습니다. 나는 지금까지 짧게 말했지만 최선의 노력은 다음과 같습니다.
find spec -name "*_test.rb" -exec echo mv {} `echo {} | sed s/test/spec/` \;
NB : exec 후에 추가 에코가 있으므로 테스트하는 동안 명령이 실행되는 대신 인쇄됩니다.
실행할 때 일치하는 각 파일 이름에 대한 출력은 다음과 같습니다.
mv original original
즉, sed에 의한 대체가 손실되었습니다. 트릭은 무엇입니까?
답변
이것은 sed
문자열 {}
을 입력으로 받기 때문에 발생합니다 .
find . -exec echo `echo "{}" | sed 's/./foo/g'` \;
foofoo
디렉토리의 각 파일에 대해 재귀 적으로 인쇄 합니다. 이 동작의 이유는 파이프 라인이 전체 명령을 확장 할 때 셸에 의해 한 번 실행되기 때문입니다.
셸을 통해 명령을 실행하지 않고 파이프 라인이나 역 따옴표에 대한 개념이 없기 때문에 모든 파일에 대해 sed
파이프 라인을 find
실행 하는 방식으로 파이프 라인 을 인용 할 방법 find
이 없습니다. GNU findutils 매뉴얼은 파이프 라인을 별도의 쉘 스크립트에 넣어 유사한 작업을 수행하는 방법을 설명합니다.
#!/bin/sh
echo "$1" | sed 's/_test.rb$/_spec.rb/'
(이 sh -c
모든 것을 하나의 명령으로 수행하기 위해 사용하는 비뚤어진 방법 과 많은 따옴표가있을 수 있지만 시도하지 않을 것입니다.)
답변
원래 문제에 가장 가까운 방법으로 해결하려면 xargs “args per command line”옵션을 사용하는 것이 좋습니다.
find . -name "*_test.rb" | sed -e "p;s/test/spec/" | xargs -n2 mv
현재 작업 디렉토리에서 파일을 재귀 적으로 찾고 원래 파일 이름 ( p
)과 수정 된 이름 ( s/test/spec/
)을 반향하여 모두 mv
쌍 ( xargs -n2
)으로 공급합니다 . 이 경우 경로 자체에는 문자열이 포함되지 않아야합니다 test
.
답변
다음과 같은 다른 방법을 고려할 수 있습니다.
for file in $(find . -name "*_test.rb")
do
echo mv $file `echo $file | sed s/_test.rb$/_spec.rb/`
done
답변
이게 더 짧아요
find . -name '*_test.rb' -exec bash -c 'echo mv $0 ${0/test.rb/spec.rb}' {} \;
답변
원하는 경우 sed없이 수행 할 수 있습니다.
for i in `find -name '*_test.rb'` ; do mv $i ${i%%_test.rb}_spec.rb ; done
${var%%suffix}
스트립 suffix
의 값으로부터 var
.
또는 sed를 사용하여 수행하려면 :
for i in `find -name '*_test.rb'` ; do mv $i `echo $i | sed 's/test/spec/'` ; done
답변
당신은 당신이 사용하고 있다고 언급 bash
, 쉘로하는 경우에 당신이 실제로 필요하지 않습니다 find
및 sed
후 당신의 이름을 변경 배치를 달성하기 위해 …
bash
쉘로 사용한다고 가정합니다 .
$ echo $SHELL
/bin/bash
$ _
… 그리고 소위 globstar
쉘 옵션을 활성화했다고 가정합니다 .
$ shopt -p globstar
shopt -s globstar
$ _
… 그리고 마지막으로 rename
유틸리티 ( util-linux-ng
패키지에 있음)를 설치했다고 가정합니다.
$ which rename
/usr/bin/rename
$ _
… 그러면 다음과 같이 bash 한 줄짜리 일괄 이름 바꾸기를 수행 할 수 있습니다 .
$ rename _test _spec **/*_test.rb
( globstar
쉘 옵션은 bash가 *_test.rb
디렉토리 계층 구조에 얼마나 많이 중첩되어 있더라도 일치하는 모든 파일을 찾도록 보장합니다 … help shopt
옵션 설정 방법을 찾는 데 사용 )
답변
가장 쉬운 방법 :
find . -name "*_test.rb" | xargs rename s/_test/_spec/
가장 빠른 방법 (프로세서 4 개가 있다고 가정) :
find . -name "*_test.rb" | xargs -P 4 rename s/_test/_spec/
처리 할 파일이 많은 경우 xargs에 파이프 된 파일 이름 목록으로 인해 결과 명령 줄이 허용되는 최대 길이를 초과 할 수 있습니다.
다음을 사용하여 시스템의 제한을 확인할 수 있습니다. getconf ARG_MAX
대부분의 리눅스 시스템에서 사용 free -b
하거나 cat /proc/meminfo
작업해야하는 RAM의 양을 찾을 수 있습니다 . 그렇지 않으면 top
시스템 활동 모니터 앱을 사용하십시오.
더 안전한 방법 (작업 할 RAM이 1000000 바이트라고 가정) :
find . -name "*_test.rb" | xargs -s 1000000 rename s/_test/_spec/