이름에 'Music'이라는 단어가 포함 된 파일과 폴더를 제외한 디렉토리의 내용을 복사하려고한다고 가정 해 봅시다.
cp [exclude-matches] *Music* /target_directory
이를 수행하기 위해 [제외 일치] 대신 무엇을해야합니까?
이름에 'Music'이라는 단어가 포함 된 파일과 폴더를 제외한 디렉토리의 내용을 복사하려고한다고 가정 해 봅시다.
cp [exclude-matches] *Music* /target_directory
이를 수행하기 위해 [제외 일치] 대신 무엇을해야합니까?
답변:
배쉬에서 당신이 가능하게하여 그것을 할 수있는 extglob다음과 같은 옵션을 (교체 ls와 함께 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
f제외하고로 시작하는 모든 것을 어떻게 일치시킬 foo까요?
extglob쉘 옵션은 당신에게 명령 줄에서 더 강력한 패턴 매칭을 제공합니다.
당신은에 그것을 설정 shopt -s extglob하고 그것을 해제 shopt -u extglob.
귀하의 예에서는 처음에 다음을 수행합니다.
$ shopt -s extglob
$ cp !(*Music*) /target_directory
전체 사용 가능한 내선는 종료 글로브의 빙 사업자 (발췌입니다 man bash) :
shopt 내장을 사용하여 extglob 쉘 옵션을 사용하면 여러 확장 패턴 일치 연산자가 인식됩니다. 패턴 목록은 |으로 구분 된 하나 이상의 패턴 목록입니다. 복합 패턴은 다음 하위 패턴 중 하나 이상을 사용하여 형성 될 수 있습니다.
- ? (pattern-list)
주어진 패턴이 0 번 또는 1 번 일치합니다.- * (pattern-list)
0 개 이상의 주어진 패턴과 일치- + (pattern-list)
주어진 패턴 중 하나 이상을 찾습니다- @ (pattern-list)
주어진 패턴 중 하나와 일치- ! (pattern-list)
주어진 패턴 중 하나를 제외한 모든 것과 일치
당신이없는 현재 디렉토리에있는 모든 파일 목록을하고 싶어한다면, 예를 들어, .c또는 .h파일을, 당신은 할 것이다 :
$ ls -d !(*@(.c|.h))
물론 일반적인 쉘 글 로빙이 작동하므로 마지막 예제는 다음과 같이 쓸 수도 있습니다.
$ ls -d !(*.[ch])
.c또는 .h파일 중 하나 가 디렉토리 인 경우 @Koveras .
D하지만 디렉토리에 포함될 수있는 서브 디렉토리의 컨텐츠는 나열 하지 않습니다 D.
bash에는 없지만 (내가 아는) :
cp `ls | grep -v Music` /target_directory
나는 이것이 당신이 찾고있는 것이 아니라는 것을 알고 있지만, 당신의 모범을 해결할 것입니다.
bash에서 대안 shopt -s extglob은 GLOBIGNORE변수 입니다. 실제로는 좋지 않지만 기억하기가 더 쉽습니다.
원래 포스터가 원하는 것일 수있는 예 :
GLOBIGNORE="*techno*"; cp *Music* /only_good_music/
완료되면 소스 디렉토리에 unset GLOBIGNORE있을 수 있습니다 rm *techno*.
꽤 간단한 for루프를 사용할 수도 있습니다 .
for f in `find . -not -name "*Music*"`
do
cp $f /target/dir
done
-maxdepth 1비 재귀 위해?
find사소한 파일 이름을 찾으면 백틱에서 사용하면 불쾌한 방식으로 중단됩니다.
개인적으로 선호하는 것은 grep과 while 명령을 사용하는 것입니다. 이를 통해 강력하면서도 읽기 쉬운 스크립트를 작성하여 원하는대로 정확하게 작업 할 수 있습니다. 또한 에코 명령을 사용하면 실제 작업을 수행하기 전에 드라 이런을 수행 할 수 있습니다. 예를 들면 다음과 같습니다.
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
bash사용할 수 while IFS='' read -r filename있지만 개행은 여전히 문제입니다. 일반적으로 ls파일을 열거하는 데 사용하지 않는 것이 가장 좋습니다 . 같은 도구 find가 훨씬 더 적합합니다.
for file in *; do case ${file} in (*Music*) ;; (*) cp "${file}" /target_directory ; echo ;; esac; done
내가 사용하지 않는 아직 여기에 보지 못한 트릭 extglob, find또는이 grep두 개의 파일 세트로 목록 및 치료하는 것입니다 "DIFF" 그들을 사용하여 comm:
comm -23 <(ls) <(ls *Music*)
commdiff여분의 주름이 없기 때문에 바람직 합니다.
이 반환 세트 1의 모든 요소, ls있다, 없다 세트 2도, ls *Music*. 이를 위해서는 두 세트가 제대로 작동하려면 정렬되어 있어야합니다. ls확장에 문제가 없고 glob 확장이 필요 하지만와 같은 것을 사용하는 경우 find반드시 호출하십시오 sort.
comm -23 <(find . | sort) <(find . | grep -i '.jpg' | sort)
잠재적으로 유용합니다.
comm -23 <(ls) exclude_these.list
이를위한 하나의 솔루션은 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가이를 제어하는 데 유용 할 수 있습니다.
find -maxdepth 1 -not -name '*Music*'/ target_directory
다음 작품은 *.txt숫자로 시작하는 파일을 제외하고 현재 디렉토리의 모든 파일을 나열합니다 .
이 작품 bash, dash, zsh다른 모든 POSIX 호환 쉘.
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
첫 번째 줄에서 패턴 /some/dir/*.txt은 이름이로 끝나는 for모든 파일을 반복합니다 ./some/dir.txt
두 번째 줄에서 case 문은 원하지 않는 파일을 제거하는 데 사용됩니다. –이 ${FILE##*/}표현식은 파일 이름 (여기 /some/dir/) 에서 선행 dir 이름 구성 요소를 제거하여 패턴이 파일의 기본 이름과 만 일치되도록합니다. (접미사를 기준으로 파일 이름 만 제거하는 경우 $FILE대신 단축 할 수 있습니다 .)
세 번째 줄에서는 casepattern [0-9]*) 줄과 일치하는 모든 파일을 건너 뜁니다 ( continue명령문은 for루프 의 다음 반복 으로 건너 뜁니다 ). –을 사용하여 문자 (a–z)로 시작하지 않는 모든 파일을 건너 뛰는 것과 같이 여기에서 더 흥미로운 것을 수행 [!a-z]*하거나 여러 패턴을 사용하여 여러 종류의 파일 이름 [0-9]*|*.bak을 건너 뛸 수 있습니다 ( 예 : 두 .bak파일 모두 파일 을 건너 뛰는 경우) 및 숫자로 시작하지 않는 파일.
*.txt단지 대신 일치했습니다 *). 지금 수정했습니다.
ls /dir/*/!(base*)