나는 현재 디렉토리 아래의 모든 디렉토리와 파일을 나열하고 다음을 사용하여 파일인지 디렉토리인지 쓰고 싶습니다.
find -exec echo `echo {} : ;if [ -f {} ]; then echo file; else echo directory;fi` \;
나는 그것이 어리석은 명령이라는 것을 알고 있으며 -type f
또는 같은 다른 명령을 사용할 수 있지만 -type d
해당 코드 조각이 예상대로 작동하지 않는 이유를 이해하고 싶습니다. 단지 디렉토리를 모두 인쇄합니다. 예를 들어 출력은 다음과 같습니다 find
.
.
./dir
./dir/file
내 코드의 출력은 다음과 같습니다
. : directory
./dir : directory
./dir/file : directory
그리고 출력
echo `echo dir/file : ;if [ -f dir/file ]; then echo file; else echo directory;fi`
예
dir/file : file
연구 Ubuntu 14.10
하고 사용하고 있어요find (GNU findutils) 4.4.2
답변1
먼저, 코드 조각이 명령을 실행합니다.
echo {} : ;if [ -f {} ]; then echo file; else echo directory;fi
명령 대체를 평가하려면 출력이 필요하기 때문입니다. 라는 파일이 없으므로 {}
출력이 생성됩니다.
{} :
directory
find
그런 다음 명령은 -exec
, echo
, {}
, 매개변수를 사용하여 실행되므로 각 파일에 대해 파일 이름 뒤에 공백 및 가 표시됩니다 .:
directory
: directory
echo {} :; …
실제로 원하는 것은 에서 찾은 모든 파일에 대해 쉘 조각을 실행하는 것입니다 find
. 이 코드 조각은 명령줄에서 데이터를 수신하므로 시작된 셸 find
이 아닌 생성된 셸 에서 실행되어야 합니다 . 따라서 실행 중인 셸에 다음을 지시해야 합니다.find
find
find
find -exec sh -c 'echo {} : ;if [ -f {} ]; then echo file; else echo directory;fi' \;
이것이 더 좋지만 여전히 옳지 않습니다. 파일 이름에 특수 문자가 포함되어 있지 않으면 일부(전부는 아님) 구현에서 작동 find
하지만 쉘 스크립트에 파일 이름을 삽입하므로 파일 이름이 임의의 쉘 명령을 실행할 수 있도록 허용합니다. $(rm -rf /)
, 그러면 명령이 rm -rf /
실행됩니다. 파일 이름을 스크립트에 전달하려면 별도의 인수로 전달하세요.
첫 번째는 echo
콜론 뒤에 개행 문자를 인쇄합니다. 이를 피하려면 echo -n
(쉘이 지원하는 경우) 또는를 사용하십시오 .printf
find -exec sh -c 'printf "%s :" "$0"; if [ -f "$0" ]; then echo file; else echo directory; fi' {} \;
-exec … {} +
더 빠른 쉘 호출 그룹화를 사용할 수 있습니다 .
find -exec sh -c 'for x; do printf "%s :" "$x"; if [ -f "$x" ]; then echo file; else echo directory; fi; done' _ {} +
답변2
if; then; else; fi
이를 수행하는 또 다른 방법은 다음과 같습니다 find
.
find |
while IFS= read -r p; do if [ -f "$p" ]; then echo file; else echo directory; fi; done