
시간이 지남에 따라 나는 동일한 패턴을 계속해서 직면했습니다. 일종의 디렉토리 구조가 있습니다.
example/
├── a
│ └── c
│ ├── d.txt (120k)
│ └── e.txt (60k)
└── b
└── f.txt (280k)
그리고 파일을 다른 디렉토리로 "복사"하고 싶습니다. 예 example_grepped
를 들어, 대신에 각각에 명령을 적용하여 구조는 동일하지만 파일을 통해 필터링된 폴더로 끝납니다. .cp
grep ERROR
grep
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/{}'