가능한 모든 하위 디렉터리에서 bash 명령을 실행하는 방법은 무엇입니까?

가능한 모든 하위 디렉터리에서 bash 명령을 실행하는 방법은 무엇입니까?

내 홈 디렉토리가 다음과 같다고 가정해 보겠습니다./home/test

그 아래에는 많은 하위 디렉터리가 있고, 그 하위 디렉터리 아래에는 많은 하위 디렉터리 등이 있습니다.

예:

/home/test
/home/test/subdir1
/home/test/subdir1/subdir2
/home/test/subdir1/subdir2/subdir3
/home/test/subdir1/subdir2/subdir4
/home/test/subdir1/subdir2/subdir4/subdir5

등...

나는 각 디렉토리를 받아들이고 단지 명령을 실행하는 간단한 스크립트를 원합니다 pwd.

답변1

병렬 솔루션 사용

작고 빠른 솔루션을 위해 GNU Parallel을 사용할 수 있습니다.

find . -type d -print0 | parallel -0 cd {}'&&' <command-name>

이는 공백과 개행 문자가 포함된 디렉토리 이름에도 절대적으로 작동합니다. 이것이 하는 일은 각 디렉터리 parallel에서 출력을 가져온 다음 . 그런 다음 디렉터리 변경이 성공하면 이 디렉터리에서 별도의 명령이 실행됩니다.find{}

while 루프를 사용하는 일반적인 솔루션

find "$PWD" -type d | while read -r line; do cd "$line" && <command-name>; done;

$PWD변수에 다음이 포함되어 있으므로 여기서는 이것이 사용됩니다 .절대 경로명령이 실행되는 현재 디렉터리입니다. 절대 경로를 사용하지 않으면 cdwhile 루프에서 오류가 발생할 수 있습니다.

이것은 더 간단한 솔루션입니다. 디렉터리 이름에 이상한 문자(예: 개행 문자)가 포함되어 있지 않는 한 대부분의 경우 작동합니다(주석 참조).

답변2

find명령은 강력하지만 사용하기가 약간 어렵습니다.
나는 그것이 당신이 필요로 하는 것을 확신합니다. 아래 명령은 당신이 요청한 "거의" 명령입니다.

find . -type d -execdir pwd \;

그러나 가장 깊은 디렉터리 수준에서는 명령이 실행되지 않습니다. 다른 디렉터리가 있는 디렉터리에서 명령이 실행됩니다.

subdir4따라서 가 포함되어 있기 때문에 실행됩니다 subdir5. 그러나 subdir5예상한 대로는 아닙니다.

-execdir더 잘 알려진 옵션 -exec(참고자료 참조 man find) 대신 이 옵션을 사용하는 것이 중요합니다 .

-exec옵션은 시작 디렉터리에서 명령을 실행하며 다른 단점도 있습니다.

    -exec command ;
           Execute command; true if 0 status  is  returned.   All  following
           arguments  to find are taken to be arguments to the command until
           an argument consisting of ';' is encountered.  The string '{}' is
           replaced  by  the current file name being processed everywhere it
           occurs in the arguments to the command,  not  just  in  arguments
           where  it  is  alone, as in some versions of find.  Both of these
           constructions might need to be escaped (with a \ ) or quoted  to
           protect  them from expansion by the shell.  See the EXAMPLES sec‐
           tion for examples of the use of the -exec option.  The  specified
           command  is  run once for each matched file.  The command is exe‐
           cuted in the starting directory.   There are unavoidable security
           problems  surrounding use of the -exec action; you should use the
          -execdir option instead.

하지만 이 옵션은 -execdir정확히 귀하가 요청한 것입니다.

   -execdir command ;
   -execdir command {} +
           Like  -exec,  but the specified command is run from the subdirec‐
           tory containing the matched  file,  which  is  not  normally  the
           directory  in  which  you  started find.  This a much more secure
           method for invoking commands, as it avoids race conditions during
           resolution  of the paths to the matched files.  As with the -exec
           action, the '+' form of -execdir will build  a  command  line  to
           process  more  than one matched file, but any given invocation of
           command will only list files that exist in the same subdirectory.
           If  you use this option, you must ensure that your $PATH environ‐
           ment variable does not reference '.'; otherwise, an attacker  can
           run any commands they like by leaving an appropriately-named file
           in a directory in which you will run -execdir.  The same  applies
           to having entries in $PATH which are empty or which are not abso‐
           lute directory names.

답변3

다른 답변 중 하나는 다음과 같습니다.

찾다. -type d -exec sh -c 'cd "$0" &&지침'{} \;

( cd명령은 성공한 경우에만 실행됩니다.) 어떤 사람들은 발견된 디렉토리( {})가 다음으로 이동 하도록 더미 매개변수를 삽입할 것을 제안했습니다 $1.

찾다. -type d -exec sh -c 'cd "$1" &&지침' foo {} ";"

물론 여기에서는 대신 임의의 문자열을 사용할 수 있습니다 foo. 일반적인 선택에는 -, --및 가 포함됩니다 sh. 이 문자열은 오류 메시지(있는 경우)에 사용됩니다. 예를 들면 다음과 같습니다.

foo: 행 0: cd:제한된 디렉토리: 권한이 거부되었습니다

그래서 sh좋은 선택인 것 같습니다.  \;그리고 ";"그것은 절대적으로 동일합니다. 그것은 단지 스타일 선호일 뿐입니다.

위 명령은 각 디렉터리에 대해 한 번씩 셸을 실행합니다. 이로 인해 약간의 성능 저하가 발생할 수 있습니다(특히 실행할 명령이 상대적으로 가벼운 경우). 대안은 다음과 같습니다

찾다. -type d -exec sh -c 'd;do(cd "$d"&&지침); 완료 'sh {} +

셸은 한 번 실행되지만 각 디렉터리에 대해 한 번씩 분기됩니다.

찾다. -type d -exec sh -c 'save_d=$PWD; 실행 cd "$d" &&지침; cd "$save_d"; 완료 ' sh {} +

하위 쉘을 생성하지 않습니다. 귀하의 질문에서 알 수 있듯이 절대 경로를 검색하는 경우 위의 내용을 결합하여 수행할 수 있습니다.

d;execute cd "$d" &&에 대해 /home/test -type d -exec sh -c '를 찾습니다.지침;완료' sh {} +

하위 쉘을 생성하지 않으며 시작점을 저장하지 않습니다.

답변4

이런 것을 사용할 수 있습니다

find /home/test/ -type d -exec bash -c '<Command to be executed>' \; 

예:

다음 명령은 pwd 명령 실행과 유사하게 디렉터리 이름을 표시합니다.

find /home/test/ -type d -exec bash -c 'echo $0' \;

관련 정보