find
다음과 같은 현재 디렉토리의 일부 파일을 수집하는 데 사용하는 스크립트에서
$ find . -name "*.h"
./foo.h
이제 접두사 foo.h
없이 그냥 출력하고 싶습니다 . ./
빈 문자열은 ""
쉘 명령의 현재 디렉토리를 나타내는 것 같습니다. 그러나 이것은 다음을 제공합니다:
$ find "" -name "*.h"
find: ftsopen: No such file or directory
그래서 나는 틀렸다. 이제 내 질문은 언제/어떻게/어디서/.. "빈 문자열(?)"이 파일 이름이나 경로 이름이 필요한 명령의 현재 디렉터리를 의미합니까? 간결하고 계몽적인 설명이 있습니까?
부가적인 질문은 위의 찾기 항목을 문자열 조작 la ${parameter#word}
또는 cut
또는 sed
? 없이 간단히 해결할 수 있는지 여부입니다.
답변1
답변2
당신은 그것을 사용할 수 있습니다 :
find * -name "*.h"
.로 시작하는 이름을 가진 현재 디렉토리의 파일은 .
무시되고, .로 시작하는 이름을 가진 파일은 -
옵션으로 해석되어 find
혼란을 야기하므로 이는 find . …
.
/
파일 이름에 ""로 끝나는 문자열이 없습니다.힌트현재 디렉토리이지만 이것이 현재 디렉토리가 다음과 같다는 의미는 아닙니다.표현하다빈 문자열(인쇄할 때 동일하게 보일 수 있지만 이는 누락된 문자열과 동일하지 않을 수 있음)
답변3
일반적으로 빈 문자열은 쉘 명령이나 시스템 호출의 경우 현재 디렉토리를 나타내지 않습니다.일부 구형 시스템에서는 작동하지만 POSIX 호환 시스템에서는 작동하지 않습니다..
때로는 빈 문자열을 전달하고 프로그램에 디렉터리 이름이 필요한 경우 프로그램이 현재 디렉터리를 사용하는 것을 알 수 있습니다. 이는 의도적인 경우도 있고, 주어진 문자열이 슬래시로 시작하지 않을 때 현재 디렉터리에 대한 절대 경로를 앞에 추가하는 부작용으로 인한 경우도 있습니다.
당신에게 가장 좋은 것은 떠나는 것입니다 ./
. 해를 끼치 지 않습니다.
파일 목록이 다음과 같은 경우
find . … | sed 's!^\./!!'
이로 인해 개행 문자가 포함된 일부 파일 이름이 손상될 수 있습니다. 이는 일반적으로 인간이 소비하는 데에는 문제가 되지 않으며, 의 출력은 find
지정되지 않기 때문에 프로그램 소비에 적합하지 않습니다. 프로그램 사용에 적합한 것을 사용하는 경우 -print0
아마도 접두사에 신경 쓰지 않을 것입니다 ./
.
find * …
대신 사용할 수 있지만 단점이 많으며 일반적으로 다음과 같은 경우에는 적합하지 않습니다 find . …
.find *
.
생략되어 있습니다.- 모든 도트 파일(이름이 또는 ..` 으로 시작하는 파일
.
)은 생략됩니다. - 현재 디렉터리에 (또는 ...이라는 파일)로 시작하는 파일 이름이 있으면
-
옵션이나 조건자로 해석됩니다.!
(
find
필터가 현재 디렉터리를 제외하는 경우 첫 번째 사항은 중요하지 않습니다. 두 번째 점의 경우 패턴을 사용하여 ..?* .[!.]* *
현재 디렉터리의 모든 파일과 일치할 수 있지만 각 패턴이 하나 이상의 파일과 일치하는지 확인하고 일치하지 않으면 무시해야 합니다. 가능하지만 매우 번거롭습니다. 마지막 비트는 스토퍼입니다. 따라서 find *
빠른 명령줄 사용에는 적합할 수 있지만 스크립트에서는 사용하지 마십시오.
또 다른 접근 방식은 쉘의 재귀적 글로빙 기능을 사용하는 것입니다.
printf '%s\n' **/*.h
shopt -s globstar
이를 위해서는 bash 및 ksh93을 통한 활성화가 필요하며 set -o globstar
기본 POSIX 셸(예: dash)에는 존재하지 않습니다. 도트 파일은 기본적으로 탐색되지 않습니다. 이를 포함하려면 먼저 shopt -s dotglob
bash 또는 ksh93 FIGNORE='@(.|..)'
에서 도트 파일을 무시하지 않도록 globbing을 활성화하세요. 또한 이 명령은 일치하는 항목이 없으면 패턴을 인쇄합니다. bash에서 실행하면 shopt -s nullglob
빈 줄이 인쇄되고 ~(N)**/*.h
ksh에서 패턴이 사용됩니다.
zsh에서는 기본적으로 재귀 와일드카드가 활성화되어 있습니다. glob 한정자를 사용 D
하여 도트 파일을 포함하고 N
일치하는 항목이 없으면 빈 줄을 인쇄합니다(기본적으로 패턴이 파일과 일치하지 않으면 zsh는 오류를 발생시킵니다). printf
위와 같이 사용 하거나
print -rl -- **/*.h(DN)
답변4
몇 가지 트릭을 사용하여 선행 없이 find 출력을 얻을 수 있습니다 ./
.
find의
-printf
옵션을 사용하고 그냥 print 하도록 지시하세요%f
. 바라보다man find
:%f는 모든 선행 디렉토리 파일 이름을 제거합니다(마지막 요소만).
예를 들어:
find . -name "*.h" -printf "%f\n"
구문 분석 출력:
find . -name "*.h" | sed 's#^./##'
-
find * -name "*.h"
다른 질문의 경우 빈 문자열은 현재 디렉터리를 나타내지 않습니다. 단지 다양한 프로그램이 현재 디렉터리를 기본 디렉터리로 갖고 있기 때문에 인수 없이 실행하면 현재 디렉터리에서 실행될 뿐입니다.