2010-11-26 6 views
8

find은 옵션의 시작으로 파일 이름의 시작 부분에 대시를 해석합니다. 친숙한 -- 트릭을 사용하면 옵션이 파일 이름 뒤에 나오므로 따옴표로 아무 효과가 없으므로 첫 번째 대시를 \-으로 바꾸어도 작동하지 않습니다. 사용자는 종종 이러한 파일 이름 앞에 ./을 붙이는 것이 좋습니다.하지만 주어진 경로가 절대 경로인지 상대 경로인지 여부를 모르는 경우 어떻게해야합니까?디렉토리에서 대시로 시작하는 파일 찾기

편집 : 하나의 해결책은 find "$(readlink -f -- "$test_filename")"인데,보기 흉한 것입니다. 더 좋은 아이디어?

편집 2 : 제안 해 주셔서 감사합니다. 이 노력으로 생긴 두 개의 스크립트는 다음과 같습니다. safe-find.sh; safe-count-files.sh

답변

3

, 그러나 나는 실제로 당신이 알아 낸 한 readlink 대안을 사용하는 것이 좋습니다. 것입니다 (...) 이후의 모든 인수 는

그래서 표현으로 --을 해석해야한다 - ''는 로 시작하는 Unix standard,

첫 번째 인수에 따라 실제로 작동하지 않습니다. thkala의 해결책이 또한 효과가 있을지 모르지만, 나는 그것을 덜 읽기 쉽게 만든다. 그래도 많은 경우에 find 호출을 수행하는 것이 더 빠를 수도 있습니다.

+0

OP의 편집 전에 내 대답은 실제로 첫 번째 oneliner보다 덜 난해하기 때문에 readlink가 포함되어 있습니다. 두 가지 프로세스 (fork 된 셸과 readlink 자체)를 두 번 실행하고 찾기 위해 인수로 여러 디렉토리가 있으면 모든 객체에 readlink를 적용하는 것이 한 가지 단점입니다 – thkala

+0

@thkala : 방금 알아 냈습니다. $ (exec readlink -f - "$ file")'는 포크 중 하나를 방지합니다. 가독성의 비용. –

+0

@larsmans : thkala의 대답은'readlink -f'가없는 시스템에서 작업 할 때 이점이 있습니다 (GNU, NetBSD 및 OpenBSD만이 가지고 있음). – Gilles

5

스크립트에있는 경우 언제든지 확인할 수 있습니다. 예 : (bash는, 경우 ksh93 또는 zsh을위한)보다 간결한 형태에서

if [[ "$DIR" = -* ]]; then 
    find ./"$DIR" 
else 
    find "$DIR" 
fi 

: bash는, KSH 또는 zsh을 위해 그들이 경우

find "${DIR/#-/./-}" 

는 당신은, 스크립트의 매개 변수를 사용하여이 작업을 수행 할 수 있습니다 모든 디렉토리 있어야 :이 조금 싼 것처럼 보일 수 있습니다

find "${@/#-/./-}" 
+0

if [ "$ DIR = - *]'는 리터럴 문자열'- *'(현재 디렉토리에서 이름이'-'로 시작하는 파일이없는 경우) 또는 가능성이 구문 오류가 발생합니다 (있을 경우) – Gilles

+0

@ 질 : 사실 ... 나에게 무슨 일이 있었는지 모르겠다 - 나는 '테스트'또는 [bash에서 사용하지 마십시오.] – thkala

0

대시 캡처하는 글로브를 사용하여이 일부 가장자리에 영향을 미친다 (하지 떠들썩한 파티를 찾을 수에 의해 해석 그래서 문구 정규 표현식을 제거하고, 글로브를 인용 업데이트 :

find . -name '[-]*' 

편집 사례).

+1

이긴하지만 리눅스 박스에 타이핑한다는 것을 알지 못했다. –

+0

@DennisWilliamson 그것은 globbing 일지 모르지만 그것은 또한 확실히 정규식입니다. 캐릭터 클래스가 있고, 카 네이션 (catenation)이 있고, 클레이 네 (Kleene) 스타가 있습니다. 캐릭터 클래스에 캐릭터가 하나 더 있다면, 교대가있을 것이며, 모든 것을 가질 수 있습니다. 그러나 기술적으로, 일련의 문자는 정규 표현식으로 사용하는 것이 좋습니다. –

+2

@ParthianShot : 쉘은'[-] *'를 모두 정규식이 아닌 glob로 처리합니다. 여기서 별표는 "0 개 이상"을 의미하지 않기 때문에 Kleene 별이 아닙니다. glob에서 와일드 카드로 "무엇이든"을 의미합니다. 여기서 표현식은 0 이상의 하이픈이 아닌 임의의 시퀀스가 ​​오는 하이픈을 의미합니다. 그러나 조기 확장을 막기 위해 인용해야합니다. –

2

특정 쉘이나 비표준 유틸리티에 대한 요구 사항이없는 모든 유닉스 계열 시스템에서 작동해야하는 방법 1입니다.

case $DIR in 
    -*) DIR=./$DIR;; 
esac 
find "$DIR" … 

위치 매개 변수에 디렉토리 목록이 있고 처리하려는 경우 다소 복잡합니다. 다음은 POSIX 쉬 솔루션입니다 :

i=1 
while [ $i -le $# ]; do 
    case $1 in 
    -*) x=./$1;; 
    *) x=$1;; 
    esac 
    set -- "[email protected]" "$x" 
    shift 
    i=$(($i + 1)) 
done 
find "[email protected]" … 

의 Bourne 쉘 및 기타 사전 POSIX 쉬 구현은 연산 및 set -- 부족, 그래서 조금 모양은 좋지입니다.

i=1 
while [ $i -le $# ]; do 
    x=$1 
    case $1 in 
    -*) x=./$1;; 
    esac 
    set a "[email protected]" "$x" 
    shift 
    shift 
    i=`expr $i + 1` 
done 
find "[email protected]" … 

readlink -f은 GNU (리눅스, Cygwin에서, 등), NetBSD 사용 ≥4.0, 오픈 BSD ≥2.2, 비지 박스로 볼 수 있습니다 ¹. Mac OS X (10.6.4 이상), HP-UX (11.22 현재), Solaris (로 GNU 도구를 설치하지 않은 경우, 그들은 PATH에 있음) OpenSolaris 200906), AIX (7.1 현재).