programing

unix/linux 쉘에서 패턴을 일치시킬 때 어떻게 역 또는 음의 와일드카드를 사용할 수 있습니까?

showcode 2023. 4. 25. 23:46
반응형

unix/linux 쉘에서 패턴을 일치시킬 때 어떻게 역 또는 음의 와일드카드를 사용할 수 있습니까?

이름에 '음악'이라는 단어가 포함된 파일 및 폴더를 제외한 디렉토리의 내용을 복사하려고 합니다.

cp [exclude-matches] *Music* /target_directory

이를 위해 [제외 매치]대신 무엇을 해야 합니까?

에서는 Bash를 활성화하여 수행할 수 있습니다.extglob이렇게 선택지를 만들어 보세요.ls와와 with와 함께요.cp을 사용하세요.)

~/foobar> shopt extglob
extglob        off
~/foobar> ls
abar  afoo  bbar  bfoo
~/foobar> ls !(b*)
-bash: !: event not found
~/foobar> shopt -s extglob  # Enables extglob
~/foobar> ls !(b*)
abar  afoo
~/foobar> ls !(a*)
bbar  bfoo
~/foobar> ls !(*foo)
abar  bbar

나중에 다음을 사용하여 extglob을 비활성화할 수 있습니다.

shopt -u extglob

»는 다음과 같습니다.extglob셸 옵션을 사용하면 명령줄에서 보다 강력한 패턴 매칭을 수행할 수 있습니다.

같같켜켜로 거예요.shopt -s extglob 그리고 끄면 됩니다.shopt -u extglob요.

이 예에서는 처음에 다음을 수행합니다.

$ shopt -s extglob
$ cp !(*Music*) /target_directory

사용 가능한 전체 확장 글로벌 연산자는 다음과 같습니다(에서 제외).man bash 다음을 수행합니다.

shopt builtin을 사용하여 extglob 쉘 옵션을 활성화하면 여러 확장 패턴 일치 연산자가 인식됩니다.pattern-list는 |로 구분된 하나 이상의 패턴 목록입니다.복합 패턴은 다음 하위 패턴 중 하나 이상을 사용하여 형성될 수 있습니다.

  • 리스트(패턴 리스트)라고 합니다.
    지정된 패턴의 0 또는 1회 발생과 일치합니다.
  • *(pattern-list)*(패턴 목록)입니다.
    지정된 패턴의 발생 횟수가 이상이면 일치합니다.
  • +(패턴 리스트)+(패턴 리스트)라고 합니다.
    지정된 패턴의 하나 의 발생과 일치합니다.
  • )@(pattern-list)라고 합니다.
    주어진 패턴 중 하나와 일치합니다.
  • )!(pattern-list)라고 합니다.
    지정된 패턴 중 하나를 제외한 모든 패턴과 일치합니다.

따라서예를 들어 현재 디렉터리에 있는 파일 중 예가 아닌 모든 파일을 나열하려는 경우에는 현을 수 있습니다..c아니면요?.h이겁니다.

$ ls -d !(*@(.c|.h))

물론 일반 셸 글로잉은 작동하므로 마지막 예제는 다음과 같이 쓸 수 있습니다.

$ ls -d !(*.[ch])

(제가 알기로는) bash는 아니지만요.

cp `ls | grep -v Music` /target_directory

이게 당신이 찾던 것이 아니라는 걸 알지만, 당신의 사례를 해결할 수 있을 거예요.

exec 명령어를 사용하는 데 드는 mem 비용을 피하고 싶다면 xargs로 더 잘 할 수 있을 것입니다.다음 사항이 보다 효율적인 대안이라고 생각합니다.

find foo -type f ! -name '*Music*' -exec cp {} bar \; # new proc for each exec



find . -maxdepth 1 -name '*Music*' -prune -o -print0 | xargs -0 -i cp {} dest/

아직 서 본 적이 없는 속임수입니다.extglob, , 입니다.find 또는 , 는는을를(으)입니다.grep두 개의 파일 목록을 세트로 처리하고 다음을 사용하여 "확산"하는 것입니다.comm다음을 참조하십시오

comm -23 <(ls) <(ls *Music*)

comm보다 바람직합니다.diff이겁니다.

이렇게 하면 세트 1, ㄴㄴ 1의 모든 요소가 반환됩니다.ls세트 2에도 없습니다.ls *Music*. 이렇게 하려면 두 세트가 정렬되어 있어야 합니다 이렇게 하려면 두 세트가 정렬되어 있어야 합니다.문제 없습니다.ls그리고 지구본 확장도 있지만, 만약 '지구본 확장을 사용한다면 '지구본 확장'을 사용해요.find, 꼭 , 을 불러주세요sort요.

comm -23 <(find . | sort) <(find . | grep -i '.jpg' | sort)

잠재적으로 유용합니다.

아주 간단한 것도 쓸 수 있어요.forloop.

for f in `find . -not -name "*Music*"`
do
    cp $f /target/dir
done

에서는 bash의 대안으로 bash를 들 수 있습니다.shopt -s extglob변수입니다.그게 더 나은 건 아니지만 기억하기가 더 쉬워요.

원본 포스터가 원하는 예를 들어 보겠습니다.

GLOBIGNORE="*techno*"; cp *Music* /only_good_music/

끝나면요unset GLOBIGNORE 수 있습니다rm *techno*이겁니다.

개인적으로 선호하는 것은 grep 및 while 명령어를 사용하는 것입니다.이렇게 하면 강력하면서도 읽을 수 있는 스크립트를 작성할 수 있으므로 원하는 대로 정확하게 수행할 수 있습니다.또한 echo 명령을 사용하여 실제 작업을 수행하기 전에 시운전을 수행할 수 있습니다.예를 들어 다음과 같습니다.

ls | grep -v "Music" | while read filename
do
echo $filename
done

복사하게 될 파일을 인쇄합니다.목록이 올바른 경우 다음 단계는 다음과 같이 echo 명령을 copy 명령으로 간단히 대체합니다.

ls | grep -v "Music" | while read filename
do
cp "$filename" /target_directory
done

이를 위한 한 가지 솔루션은 find를 통해 찾을 수 있습니다.

$ mkdir foo bar
$ touch foo/a.txt foo/Music.txt
$ find foo -type f ! -name '*Music*' -exec cp {} bar \;
$ ls bar
a.txt

찾기에는 여러 가지 옵션이 있으며, 포함하거나 제외하는 항목에 대해 구체적으로 지정할 수 있습니다.

편집: 주석의 Adam은 이것이 재귀적인 것이라고 지적했습니다.find 옵션 mindepth 및 maxdepth를 사용하면 이를 제어하는 데 유용할 수 있습니다.

다음 작품들은 모두 열거되어 있습니다.*.txt숫자로 시작하는 파일은 제외하고 현재 dir에 있습니다.

이 기능은 에서 작동합니다.bash, , 입니다.dash, , 입니다.zsh포식스입니다.

for FILE in /some/dir/*.txt; do    # for each *.txt file
    case "${FILE##*/}" in          #   if file basename...
        [0-9]*) continue ;;        #   starts with digit: skip
    esac
    ## otherwise, do stuff with $FILE here
done
  1. 첫 번째 줄에 있는 문양입니다./some/dir/*.txt이 원인이 됩니다.for루프를 반복하여 에 있는 모든 파일에 대해 반복하십시오./some/dir그 이름은 로 끝납니다..txt요.

  2. - - - ? - - 、 the 、 the 、 the the 、 the 그 ? - - – – – – – – – ? - ? -?${FILE##*/}expression은 파일 이름에서 dir 이름 구성 요소를 제거합니다(여기서 dir name은 dir name으로 지정)./some/dir/접미사를 기준으로 파일 이름만 제거하는 경우 파일 이름을 줄여서 사용할 수 있습니다.)$FILE대신. (으)ㄹ 수 있다'라고 합니다.

  3. 세 번째 줄에는 모든 파일이 일치합니다.case패턴 식식입니다.[0-9]*) 행은 건너뜁니다 ).continue다음 번 반복으로 .forloop). – 여기에서 더 흥미로운 작업을 수행할 수 있습니다. 예를 들어, 루프를 사용하여 문자(a~z)로 시작하지 않는 모든 파일을 건너뛸 수 . – 여기에서 더 흥미로운 작업을 수행할 수 있습니다. 예를 들어, 문자(a~z)로 시작하지 않는 모든 파일을 건너뛸 수 있습니다.[!a-z]*또는 여러 패턴을 사용하여 여러 종류의 파일 이름을 건너뛸 수 있습니다(예:[0-9]*|*.bak둘 다 건너뛰기 위해서입니다..bak숫자로 시작하지 않는 파일 및 파일입니다.

이것은 정확히 '음악'을 제외하고 할 수 있습니다.

cp -a ^'Music' /target

음악 같은 거 빼고 이것저것 다요?* 또는 *?음악입니다.

cp -a ^\*?'complete' /target
cp -a ^'complete'?\* /target

언급URL : https://stackoverflow.com/questions/216995/how-can-i-use-inverse-or-negative-wildcards-when-pattern-matching-in-a-unix-linu 입니다.

반응형