모든 파일을 보관하고 싶습니다.아니요다음으로 끝나는.bat
나는 노력했다
for f in $(ls | egrep -v .bat); do echo $f; done
그리고
for f in $(eval ls | egrep -v .bat); do echo $f; done
그러나 두 방법 모두 모든 내용을 인쇄하므로 동일한 결과를 생성합니다. 루프 외부에서 사용하면 자체적 ls | egrep -v .bat
으로 eval ls | egrep -v .bat
작동할 수 있습니다 for
.
편집하다
흥미롭게도 해당 플래그를 생략하면 -v
루프는 예상된 작업을 수행하고 로 시작하는 모든 항목을 나열합니다 .bat
.
질문이 무엇인지 잘 모르겠으므로 질문 제목을 자유롭게 편집하십시오.
나는 그것을 사용하고 있다GNU bash, version 4.1.10(4)-release (i686-pc-cygwin).
예
$ ls -l | egrep -v ".bat"
total 60K
-rwx------+ 1 SYSTEM SYSTEM 5.3K Jun 6 20:31 fsc*
-rwx------+ 1 SYSTEM SYSTEM 5.3K Jun 6 20:31 scala*
-rwx------+ 1 SYSTEM SYSTEM 5.3K Jun 6 20:31 scalac*
-rwx------+ 1 SYSTEM SYSTEM 5.3K Jun 6 20:31 scaladoc*
-rwx------+ 1 SYSTEM SYSTEM 5.3K Jun 6 20:31 scalap*
명령이 실행 중이지만 for 루프 내에 있지 않습니다.
$ for f in $(ls | egrep -v .bat); do echo $f; done
fsc
fsc.bat
scala
scala.bat
scalac
scalac.bat
scaladoc
scaladoc.bat
scalap
scalap.bat
scalac
scalac.bat
scaladoc
scaladoc.bat
scalap
scalap.bat
디버그 $ set -x
mike@pc /cygdrive/c/Program Files (x86)/scala/bin
$ for f in $(ls | egrep -v .bat); do echo $f; done
++ ls -hF --color=tty
++ egrep --color=auto -v .bat
+ for f in '$(ls | egrep -v .bat)'
+ echo fsc
fsc
+ for f in '$(ls | egrep -v .bat)'
+ echo fsc.bat
fsc.bat
// and so on
답변1
코드에 몇 가지 오류가 있습니다.
$(...)
설정 없이 인용되지 않은 명령 대체( ) 사용$IFS
분할+글로브 연산자는 따옴표 없이 확장됩니다. 기본값은 공백, 탭 및 줄 바꿈으로 분할하는 것입니다. 여기서는 개행 문자로만 분할하려고 하므로 IFS를 해당 값으로 설정해야 합니다. 그렇지 않으면 파일 이름에 공백이나 탭이 포함되어 있으면 작동하지 않습니다.
따옴표 없이 명령 대체를 사용합니다 set -f
.
분할+글로브 연산자는 따옴표 없이 확장됩니다. 여기서는 와일드카드가 필요하지 않습니다. 즉, 와일드카드를 scala*
일치하는 파일 목록으로 확장하는 것입니다. 쉘이 글로빙을 수행하지 않도록 하려면 다음을 사용하여 쉘을 비활성화해야 합니다.set -f
ls
별명ls -F
ls
위의 문제는 별칭을 사용 했다는 사실로 인해 더욱 악화됩니다 ls -F
. /
디렉터리 및 *
실행 파일 에 추가됩니다 . 따라서 일반적으로 scala
실행 파일 ls -F
이고 scala*
글로빙 패턴이므로 해당 파일로 시작하는 모든 파일 이름으로 확장됩니다. scala
이는 egrep -v
파일을 필터링하지 않는 것처럼 보이는 이유를 설명합니다.
파일 이름에 개행 문자가 포함되어 있지 않다고 가정합니다.
개행 문자는 파일 이름의 모든 문자만큼 유효합니다. 그래서ls
일반적으로 작동하지 않는 출력 구문 분석. 예를 들어, 이라는 파일이 포함된 디렉터리의 출력은 및 ls
이라는 a
파일이 b
포함된 디렉터리의 출력과 동일합니다 a\nb
.
위의 내용은 egrep
파일 이름이 아닌 파일 이름에 대한 행을 필터링합니다.
egrep
대신 사용grep -E
egrep
더 이상 사용되지 않습니다. grep -E
표준 등가값입니다.
.
정규식 연산자를 이스케이프 처리하지 마세요 .
위에서 egrep
활성화 했습니다.확장하다정규식이지만 확장된 RE 관련 연산자를 사용하지 않습니다. 당신이 사용하는 유일한 RE 연산자는 .
원하는 문자처럼 보이지는 않지만 모든 문자를 일치시키는 것입니다. 그래서 당신 grep -F
도 이것을 사용했을 수도 있습니다 . 또는 grep -v '\.bat'
.
정규식을 줄 끝에 고정하지 마세요.
egrep .bat
뒤에 문자가 포함된 모든 줄과 일치하므로 bat
이 정규식은 bat
첫 번째 위치에 포함되지 않은 모든 항목을 의미합니다. 그랬어야 했어 grep -v '\.bat$'
.
$f
인용없이
따옴표가 없는 확장은 분할+글로브 연산자입니다. 여기서는 둘 다 원하지 않으므로 $f
따옴표( )로 묶어야 합니다 "$f"
.
사용echo
echo
인수에서 ANSI C 이스케이프 시퀀스를 확장하거나 구현 (및/또는 환경) -n
에 따라 특별히 문자열을 처리합니다 .-e
echo
따라서 더 나은 솔루션은 다음과 같습니다.
for f in *; do
case $f in
(*.bat);;
(*) printf '%s\n' "$f"
esac
done
그러나 현재 디렉터리에 숨겨지지 않은 파일이 없으면 출력은 여전히 출력됩니다 . 로 변경하거나 를 실행하여 *
문제를 해결할 수 있습니다 .zsh
*
*(N)
bash
shopt -s nullglob
답변2
이런 식으로 파일을 구문 분석 하면 안 됩니다 ls
.
먼저 extglob globstar를 설정한 shopt -s extglob globstar
다음
for f in !(*.bat)
do
printf '%s\n' "$f"
done
사용find
find . -type f ! -name '*.bat'
파일을 보다 안전하게 처리하려면 부정 연산자를 사용하세요.
답변3
for 루프에는 본질적으로 잘못된 것이 없습니다.
$ for f in $(ls | egrep -v .bat); do echo $f; done
위 명령에 대한 결과는 다음과 같습니다.
$ for f in $(ls | egrep -v .bat); do echo $f; done
fsc
scala
scalac
scaladoc
scalap
가능한 수정
한 가지 제안은 다음과 같이 매개변수를 인용하는 것입니다 egrep
.
$ for f in $(ls | egrep -v '.bat'); do echo $f; done
Bash에서 스크립트를 작성할 때 발생할 수 있는 다른 잠재적인 문제에 대해서는 Bash Pitfalls 위키를 확인하실 수도 있습니다. 특히 그런 소리가 난다면가장 합리적인 이유왜 이 문제가 발생합니까? 반환된 파일에 공백이 포함되어 있는지 확인하세요.
디버그
시도해 볼 또 다른 방법은 bash 명령을 실행하기 전에 자세한 디버깅을 활성화하여 뒤에서 무슨 일이 일어나고 있는지 확인하는 것입니다.
이렇게 하면 디버깅이 가능해집니다.
$ set -x
그런 다음 명령을 실행합니다.
$ for f in $(ls | egrep -v .bat); do echo $f; done
++ ls --color=auto
++ egrep --color=auto -v .bat
+ for f in '$(ls | egrep -v .bat)'
+ echo fsc
fsc
+ for f in '$(ls | egrep -v .bat)'
+ echo scala
scala
+ for f in '$(ls | egrep -v .bat)'
+ echo scalac
scalac
+ for f in '$(ls | egrep -v .bat)'
+ echo scaladoc
scaladoc
+ for f in '$(ls | egrep -v .bat)'
+ echo scalap
scalap
그런 다음 비활성화하십시오.
$ set +x
CYGWIN 질문이 있으신가요?
bash
이러한 예제가 많은 기본 Linux 시스템에서 잘 실행된다는 점을 고려하면 문제는 Cygwin 및/또는 해당 특정 버전 과 관련이 있을 가능성이 높습니다 egrep
. $IFS
Windows( )와 Unix( )의 다양한 줄 구분 기호에 문제가 있는지 확인하기 위해 Bash의 필드 구분 기호에 특별한 주의를 기울일 것입니다 .0x0d,0x0a
0x0a
저는 Cygwin을 설치하지 않았으므로 이 가설을 증명할 방법이 없습니다.