내 홈 디렉토리가 다음과 같다고 가정해 보겠습니다./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
변수에 다음이 포함되어 있으므로 여기서는 이것이 사용됩니다 .절대 경로명령이 실행되는 현재 디렉터리입니다. 절대 경로를 사용하지 않으면 cd
while 루프에서 오류가 발생할 수 있습니다.
이것은 더 간단한 솔루션입니다. 디렉터리 이름에 이상한 문자(예: 개행 문자)가 포함되어 있지 않는 한 대부분의 경우 작동합니다(주석 참조).
답변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' \;