*가 도트 파일과 일치하는지 여부를 제어하기 위한 bash의 globbing 설정은 무엇입니까?

*가 도트 파일과 일치하는지 여부를 제어하기 위한 bash의 globbing 설정은 무엇입니까?

mv ./* ../somedirectory 최근에 비슷한 일을 했는데 비슷한 파일이 이동되지 않는 것을 보고 .gitignore놀랐습니다 .

내 작업의 대부분은 OS X의 zsh에서 수행되는데, 이 놀라운 사실을 통해 CentOS의 bash에서 작업을 수행할 수 있었습니다. OS X에서 bash를 시도했지만 동일한 동작을 발견했습니다. *도트 파일과 일치하지 않습니다. 이것은 나에게 매우 바람직하지 않은 것처럼 보이지만 분명히 이것이 bash의 기본값입니다. (내가 아는 한, 이것은 zsh 기본값일 수도 있지만 몇 년 전에 .zshrc에서 변경하여 다르게 작동하는 것을 잊어버렸을 수도 있습니다.)

예상대로 작동하도록 bash를 구성하려면 어떻게 해야 합니까? for *는 도트 파일을 무시하지 않고 모든 파일과 일치합니다.

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

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

답변1

불다

이미 알고 있듯이 bash는 .이름 시작 부분의 a 또는 슬래시와 일치하지 않습니다. 문제의 포인트 일치를 변경하려면 다음 옵션을 설정해야 합니다 dotglob.남자 난교:

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

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

shopt -s dotglob


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

setopt dotglob

답변2

*쉘에 의해 확장된 글로브입니다. 기본적으로 쉘은 선행 단어를 문자 그대로 입력 .하지 않는 한 이름이 a로 시작하는 파일(숨겨진 파일 또는 도트 파일이라고 함) 을 포함하지 않습니다..

*또는 [.]*또는 또는 또는에는 ?*도트 파일이 포함되어 있지 않습니다.*.*dir/*

.*아니면 dir/.*그럴 것입니다.

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

mv -- * .* /dest/

그러나 일부 쉘에는 포함 bash(포함하지 않음 zsh) mksh과 같은 버그가 있는 기능, 즉 fish포함 및 특수 디렉토리 항목의 확장이 있는데, 이는 여기서 원하지 않는 것입니다(그리고 글로브를 포함하고 싶지 않습니다). 일반적으로 이것이 내가 그것을 오류 함수라고 부르는 이유입니다.).*...

따라서 때때로 사람들이 (Bourne과 같은 쉘에서) 다음을 사용하는 것을 볼 수 있습니다.

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

이들은 세 개의 glob이며, 첫 번째는 숨겨지지 않은 파일과 일치하고, 두 번째 파일 이름은 .one 문자 이외의 문자로 시작하고 그 뒤에 오고 ., 세 번째 파일 이름은 다음으로 시작하고 ..최소한 한 문자가 옵니다.

그러나 일부 현대 쉘에는 이 문제를 해결하는 더 나은 방법이 있습니다.

다루기 힘든

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

mv -- *(D) /dest/

zshmv또한 패턴이 일치하지 않으면 명령이 실행되지 않는 Bourne 셸의 추가 버그 기능이 수정되었습니다 .

위에서 언급한 것처럼 전역 항목에도 포함되거나 .포함되지 않습니다...

mv -- * .* /dest/

안전할 것입니다. 그러나 일치하는 파일이 없거나 *일치하는 파일이 없으면 .*명령이 중단되므로 다음을 사용하는 것이 좋습니다.

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

다른 쉘과 마찬가지로 모든 glob에 도트 파일을 포함하도록 강제할 수도 있습니다(예를 들어 도트 파일을 더 자주 포함하려는 경우).

setopt dotglob

또는:

set -o dotglob

그 후 특정 글로브를 원한다면아니요도트 파일을 포함하려면 다음과 같이 작성할 수 있습니다.

echo *(^D)

또는:

echo [^.]*

불다

불행히도 bash글로벌 한정자는 없습니다. 따라서 도트 파일 포함은 전역적으로만 활성화할 수 있습니다. 에서 bash구문은 다음과 같습니다.

shopt -s dotglob

(그리고 [^.]*숨겨진 파일이 없는 glob의 경우).

의 경우 는 dotglob과 같은 전역 변수에 포함되거나 포함되지 bash않지만 과 같은 전역 변수에는 여전히 적용됩니다 ....*.*

GLOBIGNORE변수를 null이 아닌 값으로 설정 하면 자동으로 dotglob옵션이 활성화되고 glob에서 and는 제외되지만 .or(!)는 제외되지 않으므로 이 보호 기능은 거의 쓸모가 없습니다. 이렇게 할 수는 있지만 or 또는 같은 전역 변수가 삭제됩니다....*dir/.*.*/fileGLOBIGNORE='*/.:*/..:./*:../*:*/./*:*/../*'*/../*../*

더 나은 해결책은 [.]*또는 dir/[.]*( 활성화 [.]*/file) 를 사용하여 및를 제외하고 도트 파일을 dotglob확장하는 것 입니다 ....

물고기

fish.glob에는 Nor가 포함되지 않습니다 ... 일치하는 항목이 없으면 버전에 따라 zsh(또는 bash -o failglob) 처럼 작동합니다 bash -o nullglob.

mv -- * .* /dest/

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

크쉬 93

둘 다 전역 한정자가 없습니다 ksh93. 다음 명령을 사용하여 glob에 도트 파일을 포함할 수 있습니다.

FIGNORE='@(.|..)'

' 와는 반대로 bash이는 정확하며 GLOBIGNOREand를 포함하는 문제도 해결합니다..*...

야쉬

yashdot-glob옵션( ) 이 있는데 set -o dot-glob그와는 반대로 bash전역 확장이 (심지어 *) 포함되어 있어서 ...쓸모가 없습니다.

tcsh

set globdot

in 과 유사합니다 bash. 즉, and를 제외한 도트 파일을 포함 *하지만 여전히 and를 포함합니다(그리고 이를 사용하여 and 이외의 숨겨진 파일을 확장할 수 있습니다).....*...[.]*...

답변3

나는 이것을 테스트했고 문제를 해결했습니다.

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....

답변4

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

내 경험에 따르면설정되지 않음그룹은나쁜 사업거의 모든 명령(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

관련 정보