단순히 복사하는 대신 각 파일에 명령을 적용하여 디렉터리 구조를 복제하시겠습니까?

단순히 복사하는 대신 각 파일에 명령을 적용하여 디렉터리 구조를 복제하시겠습니까?

시간이 지남에 따라 나는 동일한 패턴을 계속해서 직면했습니다. 일종의 디렉토리 구조가 있습니다.

example/
├── a
│   └── c
│       ├── d.txt (120k)
│       └── e.txt (60k)
└── b
    └── f.txt (280k)

그리고 파일을 다른 디렉토리로 "복사"하고 싶습니다. 예 example_grepped를 들어, 대신에 각각에 명령을 적용하여 구조는 동일하지만 파일을 통해 필터링된 폴더로 끝납니다. .cpgrep ERRORgrep

example_grepped/
├── a
│   └── c
│       ├── d.txt (1k)
│       └── e.txt (0b)
└── b
    └── f.txt (12k)

미디어 파일(FLAC에서 MP3로, PNG에서 JPG로)을 변환할 때와 동일한 패턴이며, 이번에는 빌드 프로세스의 일부로 다양한 스키마 형식을 변환할 때입니다.

사용할 수 있는 일반 명령이 있습니까? foobar example example_grepped --command 'grep ERROR'또는 같은 것 foobar flacs mp3s --command 'ffmpeg -i {} {}.mp3'?

아마도 모호한 xargs깃발일까요? ( 파이프 를 find통해xargs거의충분하지만 대부분의 명령은 디렉토리 구조가 이미 존재할 것으로 예상합니다.)

답변1

디렉토리 구조를 별도로 다시 만들지 않고 찾을 수 있는 가장 가까운 대답은 다음을 사용하는 것입니다.설치하다:

cd example
find . -type f -exec sh -c 'grep ERROR {} | install -D /dev/stdin /tmp/example_grepped/{}' \;

불행하게도 위의 내용은 명령이 결과를 STDOUT에 전달할 수 있는 경우에만 작동할 수 있습니다.

답변2

이에 접근하는 또 다른 방법은 어쨌든 재귀 복사를 수행하는 프로그램을 사용하는 것입니다. 를 확인했는데 rsync얼핏 보면 콜백 옵션을 찾을 수 없었습니다. 그러나 gnu에는 tar파일 --to-command의 입력을 stdin. 그러면 파일을 생성하는 방법은 무엇입니까? 음, 라는 명령은 $TAR_FILENAME.

모든 것을 종합하면 기본 호출은 다음과 같습니다.

tar cf - example | tar xf - --to-command="./script example_grepped 'grep-pattern'"

스크립트는 다음과 같을 수 있습니다.

#!/bin/bash
mkdir -p $(dirname "$1/$TAR_FILENAME")
grep '$2' >"$1/$TAR_FILENAME"
exit 0

이에 접근하는 또 다른 방법은 명령줄에서 실행할 명령을 가져오는 스크립트에 tar 파이프를 래핑하는 것입니다. 그러나 구조물의 탈출은 mkdir ...dirname약간 어려울 것입니다.

답변3

#!/bin/bash

filter() {

    local target_root="${@: -1}"

    target_path=$(sed -E "s/[^/]*/$target_root/" <<< "$1")
    target_dir=$(dirname "$target_path")

    mkdir -p "$target_dir"

    if [[ -f $1 ]]; then
        # do your grep thing here
        grep burger "$1" > "$target_path"
    fi
}

export -f filter
source_root="example"
target_root="example_grepped"

find "$source_root/" -print0 | xargs -0 -I content bash -c "filter 'content' '$target_root'"

이 스크립트는 공백이 포함된 디렉터리 및 파일 이름에도 작동합니다.

소스 디렉터리("example")가 있는 위치에서 이 스크립트를 실행합니다.

답변4

GNU Parallel을 사용하면 다음과 같은 작업을 수행할 수 있습니다.

cd src
find . -type f | parallel 'mkdir -p ../dst/{//}; dostuff --input {} --output ../dst/{}'

관련 정보