*가 도트 파일과 일치하는지 여부를 제어하기 위해 글로시에 대한 bash의 설정은 무엇입니까


12

최근에 비슷한 것을 할 때 놀랐고 같은 mv ./* ../somedirectory 파일 .gitignore이 이동 하지 않았다는 것을 알았 습니다.

OS X의 zsh에서 대부분의 작업을 수행하며 CentOS의 bash에서 놀랍습니다. OS X에서 bash를 시도했지만 동일한 동작을 발견했습니다 *. 점 파일과 일치하지 않습니다. 이것은 나에게 매우 바람직하지 않은 것처럼 보이지만 분명히 bash 기본값입니다. (내가 기억하는 모든 것의 zsh 기본값 일 수도 있지만, .zshrc에서 몇 년 전에 변경되어 다르게 작동하는 것을 잊었을 수도 있습니다.)

bash가 예상대로 작동하도록 구성하는 방법 : *는 모든 파일과 일치하고 도트 파일을 무시하지 않습니다.

이것이 명확하지 않은 경우 재현 방법은 다음과 같습니다.

cd /tmp
mkdir {t,d}est
touch test/{.,}{1,2,3,4,5,6,7}
ls -hal test
mv test/* dest
ls -hal test     # notice dot files are still there
ls -hal dest     # notice only some files were mv'ed


예, 관련이 있습니다. 검색했을 때 나타나지 않았을 것입니다 (아마도 그 질문자가 globbing 또는 dot 파일을 언급하지 않았기 때문에). 그러나 실제로 다른 질문입니다. 그는 파일 이동 방법을 묻고 있었고 쉘 동작, 특히 bash를 변경하는 방법을 묻고있었습니다. 나는 그 질문이 나에게 나타 났는지 묻지 않았을 수도 있지만 (너무 완전하고 철저한 대답에는 bash 설정이 포함되어 있기 때문에) 여전히 다른 질문이며 내 질문에 대한 답을 찾는 사람이 반드시 찾을 필요는 없습니다. 그의 질문.
iconoclast

"나의 질문에 대한 답을 찾는 사람이 반드시 그의 질문을 찾을 필요는 없습니다"라는 사업이 바로 우리가 질문을 중복으로 종결하는 이러한 방법을 가지고있는 이유입니다.
Gilles 'SO- 악의를 멈춰라'

예,하지만 요점을 놓친 것 같습니다 . 다른 질문 입니다.
iconoclast

답변:


14

세게 때리다

이미 알고 있듯이 bash는 .이름의 시작 부분이나 슬래시 와 일치하지 않습니다 . 점과 일치하는 항목을 변경하려면 man bashdotglob 옵션 을 설정해야합니다 .

dotglob 설정하면 bash는`. '로 시작하는 파일 이름을 포함합니다. 에
    경로명 확장의 결과

bash를 사용하여 활성화 / 설정하려면 다음과 shopt같이하십시오.

shopt -s dotglob


zsh의 경우 dotglob옵션 을 사용할 수도 있지만 다음 setopt과 같이 활성화해야합니다.

setopt dotglob

2
을 사용 zsh하면 더 나은 옵션을 사용 하여 글로브별로 도트 글로브 를 활성화 할 수 있습니다 .mv test/*(D) /dest
Stéphane Chazelas

7

이것을 테스트하고 문제를 해결합니다.

shopt -s dotglob

산출:

~/stackexchangeanswers/40662$ ls -hal dest
total 8.0K
drwxr-xr-x 2 jodiec jodiec 4.0K 2012-06-12 22:15 .
drwxr-xr-x 4 jodiec jodiec 4.0K 2012-06-12 22:15 ..
-rw-r--r-- 1 jodiec jodiec    0 2012-06-12 22:15 1
-rw-r--r-- 1 jodiec jodiec    0 2012-06-12 22:15 .1
-rw-r--r-- 1 jodiec jodiec    0 2012-06-12 22:15 2
-rw-r--r-- 1 jodiec jodiec    0 2012-06-12 22:15 .2
-rw-r--r-- 1 jodiec jodiec    0 2012-06-12 22:15 3
-rw-r--r-- 1 jodiec jodiec    0 2012-06-12 22:15 .3
...snipped....

죄송하지만 Ulrich가 먼저 대답했습니다.
iconoclast 2016 년

3
우리는 모두 같은 팀에 있습니다. 괜찮아.
Jodie C

6

*쉘에 의해 확장되는 glob입니다. 기본적으로 셸에는 .선행을 .그대로 입력 하지 않으면 이름이 (숨겨진 파일 또는 도트 파일이라고 함) 시작하는 파일은 포함되지 않습니다 .

*또는 [.]*또는 ?*또는 *.*또는 dir/*dotfiles 포함되지 않습니다.

.*또는 dir/.*의지.

그래서 당신은 할 수 있습니다 :

mv -- * .* /dest/

그러나 등 일부 쉘 bash(하지만 zsh, mksh아니다는 fish의 확장이 있음)이 misfeature을 .*인클루드 .하고 ..당신이 (내가 그것을 misfeature 부르는 이유 인 포함하도록 글로브를 원하고 일반적으로 결코) 여기 원하지 않는 특수 디렉토리 항목을.

이런 이유로 사람들은 때때로 (Bourne과 같은 껍질에서) 다음을 사용합니다.

mv -- * .[!.]* ..?* /dest/

그것은 숨겨지지 않은 파일과 일치하는 첫 번째 글러브, 첫 번째 파일 이름 .은 다른 문자로 .시작하고 세 번째 파일 이름 ..은 적어도 하나의 문자로 시작 합니다.

그러나 일부 현대 껍질에는 더 나은 방법이 있습니다.

zsh

zsh사용하면 (D)glob 한정자를 사용하여 glob에 도트 파일이 포함되도록 지정할 수 있습니다 .

mv -- *(D) /dest/

zsh또한 패턴이 일치하지 않으면 mv명령이 실행 되지 않는 Bourne 쉘의 다른 잘못된 기능이 수정되었습니다 .

위에서 말했듯이 그것은 또한 그것의 globs에 포함 .되지도 않을 것입니다...

mv -- * .* /dest/

안전합니다. 그러나 거기에는 파일 일치하지 않는 경우는 *또는 일치하는 파일 .*이 사용하는 것이 좋습니다 것 때문에 명령이 중단되지 않습니다 :

mv -- (*|.*) /dest/

다른 쉘과 마찬가지로 다음과 같이 모든 글로브에 점 파일을 포함 시키도록 강제 할 수 있습니다 (예 : 점 파일을 자주 포함시키지 않으려는 경우).

setopt dotglob

또는:

set -o dotglob

그 후, 특정 glob dotfile을 포함 하지 않기를 원한다면, 그것을 쓸 수 있습니다 :

echo *(^D)

또는:

echo [^.]*

세게 때리다

불행히도 bashglob 한정자가 없습니다. 따라서 전 세계적으로 도트 파일 포함을 사용하도록 설정했습니다. 에서 bash, 구문은 다음과 같습니다

shopt -s dotglob

( [^.]*숨겨진 파일이없는 글로브에 사용 ).

dotglob, bash포함되지 않습니다 ...같은 globs와의 *,하지만 여전히 같은 globs와 대한 않습니다 .*.

당신은 설정하면 GLOBIGNORE뭔가 비어에 변수를, 그 다음 자동으로 할 수 있습니다 dotglob옵션을 제외 .하고 ..에서 .*globs와 있지만에서 dir/.*또는 .*/file사람을 (!) 그 안전 장치가 꽤 쓸모가 있도록. 당신은 할 수 GLOBIGNORE='*/.:*/..:./*:../*:*/./*:*/../*'있지만, 그것은 같은 globs의 휴식 것 */.또는 ./*../*.

더 나은 작업 주위는 사용하는 것 [.]*또는 dir/[.]*[.]*/file(함께 dotglob사용)를 제외하고 dotfiles을 확장 .하고 ...

물고기

fish글로브에는 .nor가 포함 되지 않습니다 ... 일치하지 않으면 버전에 따라 zsh(또는 bash -o failglob) 또는 과 같이 작동합니다 bash -o nullglob.

mv -- * .* /dest/

숨겨진 파일과 숨겨지지 않은 파일이 모두 있으면 작동합니다. 그렇지 않으면 YMMV 및 일부 버전 mv -- /dest의 경우 파일이 없으면 호출 될 수 있습니다 .

ksh93

글로브 한정자가 ksh93없습니다. 다음을 사용하여 glob에 도트 파일을 포함 할 수 있습니다.

FIGNORE='@(.|..)'

달리 bashGLOBIGNORE도 제대로하고있어, 문제 해결 .*을 포함한 ....

야쉬

yashdot-glob옵션 ( set -o dot-glob)하지만, 반대로 bash, (심지어의 글로브 확장이 *)를 포함 .하고 ..꽤 쓸모 정도.

tcsh

set globdot

처럼 작품 bash, 즉는 *제외 점 파일 포함 ...하지만 .*여전히 포함 .하고 ..(그리고 당신이 사용할 수 [.]*를 제외하고 숨겨진 파일을 확장 .하고 ..).


4

bash에서 일치하는 도트 파일을 인쇄하고 무시하는 가장 쉬운 방법 은 다음 ...같습니다.

$ GLOBIGNORE=/+/
$ printf '%s\n' *


테스트하려면 :

$ cd tmp; mkdir empty; cd empty; touch {,.}{a..h}
$ GLOBIGNORE=/+/
$  ls *
a  .a  b  .b  c  .c  d  .d  e  .e  f  .f  g  .g  h  .h

.and를 제외하고 점이 있거나없는 모든 파일을 인쇄했습니다 ...

귀하의 예도 올바르게 작동합니다.

$ cd /tmp; mkdir {t,d}est; touch test/{,.}{a..h}
$ mv test/* dest/
$ ls -a test
.  ..
$ ls -a test/*
ls: cannot access test/*: No such file or directory

중요한 파일이 없습니다.
시스템 파일은 . ..여전히 존재하지만 셸 확장 (* 사용)에는 포함되지 않습니다.

그리고 dest ination 디렉토리에는 모든 파일이 들어 있습니다 :

$ cd dest
$ ls -a *
a  .a  b  .b  c  .c  d  .d  e  .e  f  .f  g  .g  h  .h

왜?

GLOBIGNORE를 설정하면 다음 과 같은 부작용 이 있기 때문에 작동합니다 .

  • shopt -s dotglob확장에서 dotglob ( )를 math 도트 파일로 설정하십시오 .
  • 파일 이름 ...GLOBIGNORE이 널 (null)을 설정하지 않을 경우 무시됩니다.

매뉴얼의 세부 사항 : LESS=+'/The GLOBIGNORE' man bash.

또한 GLOBIGNORE 변수에 파일 이름과 일치하지 않는 이름
, 슬래시 (및 이중 예방 조치) 를 포함하도록 변수를 설정해야합니다 .

$ GLOBIGNORE=/+/

*에 일치하는 파일이 없을 때을 얻는 것을 피해야하는 경우 nullglob를 설정하는 것이 유용 할 수 있습니다 *.


0

GLOBIGNORE = / + / @ user79743의이 설정에 관심이 있습니다.

내 경험상 dotglob 설정 을 해제하는 것은 거의 모든 명령 (cp, mv 등)에 좋지 않습니다 . 그러나 nullglob (특히 정규 표현식을 사용하여 탈출해야 함)를 설정 하는 것도 마찬가지 입니다.

그럼에도 불구하고 프로그램 시작 부분에서 설정해야하지만 cp, mv 등의 명령을 호출하는 특정 부분을 방해하거나 정규 표현식을 사용하는 경우 다음과 같이하십시오.

  # set dotglob, unset nullglob AFTER this
  is_nullglob=$( shopt -s | egrep -i '.*nullglob' )
  is_dotglob=$( shopt -s | egrep -i '.*dotglob' )
  [[ $is_nullglob ]] && shopt -u nullglob
  [[ ! $is_dotglob ]] && shopt -s dotglob
  # ... call commands ...
  # .....................
  # reset dotglob, nullglob to their previous values
  [[ $is_nullglob ]] && shopt -s nullglob
  [[ ! $is_dotglob ]] && shopt -u dotglob
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.