파일을 찾고, 변경 사항을 적용하고, 다른 이름으로 다른 디렉토리에 쓰는 간단한 방법이 있습니까?

파일을 찾고, 변경 사항을 적용하고, 다른 이름으로 다른 디렉토리에 쓰는 간단한 방법이 있습니까?

foo파일 경로를 사용하고, 파일을 읽고, 일부 변경 사항을 적용하고, 변경된 파일을 표준 출력으로 출력하는 스크립트를 작성했습니다 .

foo src/file.foo > dest/file.changed.foo # works fine
cat src/file.foo | foo > dest/file.changed.foo # also works fine

이제 이 명령을 디렉터리의 여러 파일에 적용하고 각 파일에 대해 다음을 수행하려고 합니다.

src/file.foo --> foo --> 대상/file.changed.foo

기반으로답변유제나는 다음을 생각해 냈습니다.

find src -name '*.foo' \
  -exec bash -c 'for x; do dest=${x/src/dest}; foo ${x} > ${dest/\.foo$/.changed.foo}; done' _ {} +

위의 방법은 효과가 있지만 문제는 일상적으로 사용하기에는 너무 복잡하다는 것입니다.더 쉬운 방법은 없을까요?foo일을 복잡하게 만드는 방식이 아닐까 싶습니다 .

답변1

재귀 와일드카드를 사용하면 입력과 조작이 훨씬 줄어듭니다. 배쉬에서는 다음을 입력하세요.shopt -s globstar당신의 .bashrc. ksh93에서는 재귀 와일드카드가 필요합니다 set -o globstar. zsh에서는 기본적으로 사용할 수 있습니다. Bash에서 재귀 와일드카드는 디렉터리에 대한 심볼릭 링크에서도 재귀됩니다.

문자열 작업을 저장하려면 먼저 소스 트리의 상단(또는 대상 트리의 상단)으로 변경합니다.

cd foo
for x in **/*.foo; do foo "$x" >"../dest/${x%.*}.changed.foo"; done

파일 이름에 공백이나 와일드카드가 포함되지 않은 경우 큰따옴표를 생략할 수 있습니다.

zsh에서는 큰따옴표가 필요하지 않으며 현재 디렉토리를 변경하지 않고도 더 많은 입력을 절약할 수 있습니다.

for x in src/**/*.foo; do foo $x >../dest/${${x#*/}%.*}.changed.foo; done
for x in src/**/*.foo; do foo $x >../dest/${x#*/}:r.changed.foo; done
for x (src/**/*.foo) foo $x >../dest/${x#*/}:r.changed.foo

이 작업을 자주 수행하는 경우 예를 들어 GNUmakefile에서 빌드 규칙을 정의해야 합니다(탭을 사용하여 8개의 공백을 사용함).

source_files = $(shell find src -name '*.foo')
destination_files = $(patsubst src/,dest/,$($(source_files)%.foo=.changed.foo))

default: all-foo
all-foo: $(destination_files)

dest/%.changed.foo: src/%.foo
        foo $< >$@

답변2

파일 이름에 개행 문자가 포함되어 있지 않다고 가정합니다.

find src -name '*.foo' -type f | \
    while IFS= read -r sf; do
        df=dest/${sf##./src/} && \
        mkdir -p "$(dirname "$df")" && \
        foo "$sf" >"${df%%.foo}.changed.foo"
    done

답변3

소스 파일 트리가 없다고 가정하면(예: no src/dir1/a.foo; 모두 src디렉토리에 직접 있음) find래퍼가 필요하지 않으며 셸에서 직접 실행할 수 있습니다.

for x in src/*.foo
do
  dest="${x/src/dest}"
  foo "$x" > "${dest/%.foo/.changed.foo}"
done

여기서 복잡한 점은 파일 이름을 변경하고 싶은데 이것이 foo.

foo현재 디렉터리에서 실행할 필요가 없다면 조금 더 쉽게 만들 수 있습니다.

cd src
for x in *.foo
do
  foo "$x" > "../dest/${x/%.foo/.changed.foo}"
done

확장자를 변경하고 싶지 않다면 이것이 가장 간단한 루프입니다.

cd src
for x in *.foo
do
  foo "$x" > "../dest/$x"
done

문자를 전략적으로 사용하면 이러한 모든 루프를 한 줄로 바꿀 수 있습니다 ;. 예를 들어 첫 번째 루프는 다음과 같습니다.

for x in src/*.foo; do dest="${x/src/dest}" ; foo "$x" > "${dest/%.foo/.changed.foo}" ; done

관련 정보