누군가 다음을 수행하기 위해 코드를 제공 할 수 있습니까? 파일 디렉토리가 있다고 가정하십시오. 파일 디렉토리는 모두 프로그램을 통해 실행되어야합니다. 프로그램은 결과를 표준 출력으로 출력합니다. 디렉토리로 이동하여 각 파일에서 명령을 실행하고 하나의 큰 출력 파일로 출력을 연결하는 스크립트가 필요합니다.
예를 들어, 1 파일에서 명령을 실행하려면 다음을 수행하십시오.
$ cmd [option] [filename] > results.out
누군가 다음을 수행하기 위해 코드를 제공 할 수 있습니까? 파일 디렉토리가 있다고 가정하십시오. 파일 디렉토리는 모두 프로그램을 통해 실행되어야합니다. 프로그램은 결과를 표준 출력으로 출력합니다. 디렉토리로 이동하여 각 파일에서 명령을 실행하고 하나의 큰 출력 파일로 출력을 연결하는 스크립트가 필요합니다.
예를 들어, 1 파일에서 명령을 실행하려면 다음을 수행하십시오.
$ cmd [option] [filename] > results.out
답변:
다음 bash 코드는 $ file을 명령에 전달합니다. 여기서 $ file은 / dir의 모든 파일을 나타냅니다.
for file in /dir/*
do
cmd [option] "$file" >> results.out
done
예
el@defiant ~/foo $ touch foo.txt bar.txt baz.txt
el@defiant ~/foo $ for i in *.txt; do echo "hello $i"; done
hello bar.txt
hello baz.txt
hello foo.txt
/dir/
루프는 여전히 '*'for for 값으로 한 번 실행 $file
되므로 바람직하지 않습니다. 이를 피하려면 루프 지속 시간 동안 nullglob를 활성화하십시오. 루프 전에이 줄을 추가 shopt -s nullglob
하고, 루프 후이 줄을 shopt -u nullglob #revert nullglob back to it's normal default state
.
done >results.out
(여기서 내가 가정 한 것처럼 추가 대신 덮어 쓸 수 있음).
이건 어때요:
find /some/directory -maxdepth 1 -type f -exec cmd option {} \; > results.out
-maxdepth 1
argument는 find가 서브 디렉토리로 재귀 적으로 내려가는 것을 방지합니다. (이러한 중첩 디렉토리를 처리하려면이를 생략 할 수 있습니다.)-type -f
일반 파일 만 처리되도록 지정합니다.-exec cmd option {}
찾은 각 파일에 대해 cmd
지정된 option
파일 이름으로 대체 하여 실행 하도록 지시합니다.{}
\;
명령의 끝을 나타냅니다.cmd
실행 의 출력 이
results.out
그러나 파일이 처리되는 순서에 관심이 있다면 루프를 작성하는 것이 좋습니다. 나는 find
파일을 inode 순서로 처리 한다고 생각 하지만 (내가 틀릴 수도 있지만) 원하는 것이 아닐 수도 있습니다.
stat
and와 같은 다른 명령을 사용하여 정렬을 수행 할 수도 있습니다 sort
.
-exec
옵션 후에 어떻게 연결 합니까? 작은 따옴표 나 다른 것으로 포장해야합니까?
find
옵션을 사용하여 파일 이름 패턴으로 필터링 할 수 있고 항상 -name
단일 명령으로 수행 할 수 있는 최상의 옵션 입니다.
-exec
옵션을 추가하십시오 :find . -name "*.txt" -exec echo {} \; -exec grep banana {} \;
받아 들여 지거나 투표율이 높은 답변은 훌륭하지만 몇 가지 중요한 세부 정보가 부족합니다. 이 글은 쉘 경로 이름 확장 (글로브)이 실패 할 때, 파일 이름에 개행 / 대시 기호가 포함되어 있고 결과를 파일.
디렉토리를 사용하여 쉘 글로브 확장을 실행할 때 디렉토리에 파일 *
이 없고 확장되지 않은 글로브 문자열이 실행될 명령으로 전달되어 바람직하지 않은 결과가 발생할 수있는 경우 확장에 실패 할 수 있습니다. bash
쉘이 사용하기위한 확장 된 쉘 옵션을 제공합니다 nullglob
. 따라서 루프는 기본적으로 파일이 들어있는 디렉토리 내부에서 다음과 같이됩니다
shopt -s nullglob
for file in ./*; do
cmdToRun [option] -- "$file"
done
이렇게하면 표현식 ./*
이 파일을 반환하지 않을 때 (루프 가 비어있는 경우) for 루프를 안전하게 종료 할 수 있습니다.
또는 POSIX 호환 방법 ( nullglob
인 bash
특정)
for file in ./*; do
[ -f "$file" ] || continue
cmdToRun [option] -- "$file"
done
이를 통해 표현식이 한 번 실패하고 [ -f "$file" ]
확장되지 않은 문자열 ./*
이 해당 디렉토리에서 유효한 파일 이름 인지 여부를 확인하면 루프 내부로 이동할 수 있습니다. 따라서이 조건이 실패 continue
하면 for
루프를 다시 사용 하여 루프 가 다시 실행되지 않습니다.
또한 --
파일 이름 인수를 전달하기 직전에 사용법에 유의하십시오 . 앞에서 언급했듯이 셸 파일 이름은 파일 이름의 아무 곳에 나 대시를 포함 할 수 있기 때문에 필요합니다. 일부 쉘 명령은이를 해석하여 이름이 올바르게 인용되지 않은 경우이를 명령 옵션으로 취급하고 플래그가 제공되는지 생각하는 명령을 실행합니다.
이 --
경우 명령 줄 옵션의 끝을 알립니다. 즉, 명령은이 시점 이후의 문자열을 명령 플래그로 해석하지 말고 파일 이름으로 만 해석해야합니다.
파일 이름을 큰 따옴표로 묶으면 이름에 glob 문자 나 공백이 포함 된 경우가 해결됩니다. 그러나 * nix 파일 이름에는 개행 문자도 포함될 수 있습니다. 따라서 유효한 파일 이름의 일부가 될 수없는 유일한 문자 (널 바이트 ( \0
))로 파일 이름을 구분합니다 . 이후 bash
내부적으로 사용하는 C
널 바이트 문자열의 끝을 표시하는 데 사용되는 스타일 문자열을,이에 적합한 후보입니다.
따라서 printf
쉘 옵션을 사용하여 명령 -d
옵션을 사용 하여이 NULL 바이트로 파일을 구분하면 다음과 같이 read
할 수 있습니다
( shopt -s nullglob; printf '%s\0' ./* ) | while read -rd '' file; do
cmdToRun [option] -- "$file"
done
nullglob
과는 printf
감싸된다 (..)
방지하기 때문에, 그들은 기본적으로 서브 쉘 (자식 쉘)에서 실행되는 방법을 nullglob
명령이 종료되면, 부모 쉘에 반영하기 위해 옵션을 선택합니다. -d ''
의 옵션 read
명령은 하지 그래서 필요 POSIX 호환 bash
이 수행하는 쉘. find
명령을 사용하면 다음과 같이 할 수 있습니다
while IFS= read -r -d '' file; do
cmdToRun [option] -- "$file"
done < <(find -maxdepth 1 -type f -print0)
내용은 find
지원하지 않습니다 구현 -print0
합니다 (GNU와 FreeBSD의 구현 제외), 이것은 사용하여 에뮬레이션 할 수 있습니다printf
find . -maxdepth 1 -type f -exec printf '%s\0' {} \; | xargs -0 cmdToRun [option] --
또 다른 중요한 수정은 많은 수의 파일 I / O를 줄이기 위해 리디렉션을 for 루프 밖으로 이동시키는 것입니다. 루프 내에서 사용될 때, 쉘은 for 루프의 각 반복에 대해 시스템 호출을 두 번 실행해야합니다. 한 번은 파일과 연관된 파일 설명자를 열고 한 번은 닫습니다. 큰 반복을 실행하면 성능에 병목 현상이 발생합니다. 루프 외부로 옮기는 것이 좋습니다.
이 수정으로 위의 코드를 확장하면 할 수 있습니다
( shopt -s nullglob; printf '%s\0' ./* ) | while read -rd '' file; do
cmdToRun [option] -- "$file"
done > results.out
기본적으로 파일 입력의 각 반복에 대한 명령 내용을 stdout에 넣고 루프가 끝나면 대상 파일을 한 번 열어 stdout의 내용을 쓰고 저장하십시오. 동일한 find
버전은
while IFS= read -r -d '' file; do
cmdToRun [option] -- "$file"
done < <(find -maxdepth 1 -type f -print0) > results.out
때로는 작업을 수행하는 빠르고 더러운 방법 중 하나가 있습니다.
find directory/ | xargs Command
예를 들어 현재 디렉토리의 모든 파일에서 여러 줄을 찾으려면 다음을 수행하십시오.
find . | xargs wc -l
~/.local/share/steam
. Ran steam. 그것은 사용자가 소유 한 시스템의 모든 것을 삭제했습니다. "와 같은 것으로 끝납니다 . 버그 보고서.
한 디렉토리에서 다른 디렉토리로 모든 .md 파일을 복사해야 했으므로 여기에 내가 한 일이 있습니다.
for i in **/*.md;do mkdir -p ../docs/"$i" && rm -r ../docs/"$i" && cp "$i" "../docs/$i" && echo "$i -> ../docs/$i"; done
어느 것이 읽기 어렵 기 때문에 분석해 봅시다.
먼저 파일과 함께 디렉토리에 들어갑니다.
for i in **/*.md;
패턴의 각 파일마다
mkdir -p ../docs/"$i"
파일을 포함하는 폴더 외부의 문서 폴더에 해당 디렉토리를 만드십시오. 해당 파일과 이름이 같은 추가 폴더를 만듭니다.
rm -r ../docs/"$i"
결과로 생성 된 추가 폴더를 제거합니다 mkdir -p
cp "$i" "../docs/$i"
실제 파일을 복사
echo "$i -> ../docs/$i"
당신이 한 일을 에코
; done
그 이후 행복하게 살았습니다
**
하려면 globstar
쉘 옵션을 설정해야합니다 :shopt -s globstar
@Jim Lewis의 접근 방식을 기반으로합니다.
다음은 find
수정 날짜별로 파일을 사용 하고 정렬 하는 빠른 솔루션입니다 .
$ find directory/ -maxdepth 1 -type f -print0 | \
xargs -r0 stat -c "%y %n" | \
sort | cut -d' ' -f4- | \
xargs -d "\n" -I{} cmd -op1 {}
정렬은 다음을 참조하십시오.
http://www.commandlinefu.com/commands/view/5720/find-files-and-list-them-sorted-by-modification-time
-print0
에 대한 find
및 -0
에 xargs
있는 대신 (줄 바꿈 포함) 공백의 널 문자를 사용합니다.
-print0
것이 도움이되지만 전체 파이프 라인은 이와 같은 것을 사용해야하지만 sort
그렇지 않습니다.
Jim Lewis의 대답 과 잘 작동한다는 것을 알았습니다 .
$ export DIR=/path/dir && cd $DIR && chmod -R +x *
$ find . -maxdepth 1 -type f -name '*.sh' -exec {} \; > results.out
정렬 순서대로 실행하려면 다음과 같이 수정하십시오.
$ export DIR=/path/dir && cd $DIR && chmod -R +x *
find . -maxdepth 2 -type f -name '*.sh' | sort | bash > results.out
예를 들어, 다음 순서로 실행됩니다.
bash: 1: ./assets/main.sh
bash: 2: ./builder/clean.sh
bash: 3: ./builder/concept/compose.sh
bash: 4: ./builder/concept/market.sh
bash: 5: ./builder/concept/services.sh
bash: 6: ./builder/curl.sh
bash: 7: ./builder/identity.sh
bash: 8: ./concept/compose.sh
bash: 9: ./concept/market.sh
bash: 10: ./concept/services.sh
bash: 11: ./product/compose.sh
bash: 12: ./product/market.sh
bash: 13: ./product/services.sh
bash: 14: ./xferlog.sh
특정 조건에 따라 무제한 깊이로 실행하려면 다음을 사용할 수 있습니다.
export DIR=/path/dir && cd $DIR && chmod -R +x *
find . -type f -name '*.sh' | sort | bash > results.out
그런 다음 자식 디렉토리의 각 파일 위에 다음과 같이 넣으십시오.
#!/bin/bash
[[ "$(dirname `pwd`)" == $DIR ]] && echo "Executing `realpath $0`.." || return
부모 파일의 본문 어딘가에 :
if <a condition is matched>
then
#execute child files
export DIR=`pwd`
fi
ls <directory> | xargs cmd [options] {filenames put in here automatically by xargs} [more arguments] > results.out