다음 파일/디렉터리가 포함된 디렉터리가 있다고 가정해 보겠습니다.
google
apple
mozilla foundation # a file with spaces
browsers
browsers
그래서 파일을 디렉토리 로 옮기고 싶습니다 . 내가 작성한 스크립트는 다음과 같습니다.
for d in $(ls); do
if ! [ "$d" == "browsers" ]; then
mv "$d" "browsers"
fi
done
그런 다음 갔지만 google
얻었 습니다.apple
browsers
mv: cannot stat 'mozilla': No such file or directory
mv: cannot stat 'foundation': No such file or directory
분명히 문제는 변수의 공백입니다. 이 문제를 처리하는 올바른 방법은 무엇입니까?
물론, 이 작업을 수행하려면 더 우아한 한 줄 명령이 있어야 한다고 확신하지만 공백이 있는 변수를 어떻게 사용해야 하는지 알고 싶습니다.
답변1
하다아니요사용한:
for d in $(ls)
대신 이것을 사용하십시오:
for d in *
이를 사용할 때 두 가지 문제점은 $(ls)
쉘이 결과를 $(ls)
다음과 같이 적용한다는 것입니다.분사그리고경로명 확장. 당신이 생각하는 한 그것은 그렇습니다분사이로 mozilla foundation
인해 mozilla
및 가 됩니다 foundation
.
를 사용하지 않는 이유에 대한 자세한 내용은 $(ls)
다음을 참조하세요."뭐해 $(ls *.txt)
?"
디렉토리에 숨겨지지 않은 파일이 없는 경우를 고려해야 하는 경우(이 경우는 루프에서 for i in $(ls)
한 번의 패스를 수행하는 대신( *
에서 제외) 루프에서 어떤 패스도 수행하지 않기 때문에 더 좋아 보일 수 있습니다.) 일치하지 않는 글로브로 확장하지 않도록 쉘에 지시하고 싶습니다.$i
for i in *
zsh
zsh
:for i in *(N)
ksh93
:for i in ~(N)*
bash4.4+
:f() { local -; shopt -s nullglob; for i in *; ...; done; }; f
(이 옵션을 로컬로 사용하는 것이 강조됩니다 ( 기본 옵션과 유사한 동작nullglob
에 대해서는 이 옵션도 참조하십시오 )).failglob
zsh
yash
:(그런 다음 재설정합니다. 내가 아는 한set -o nullglob
로컬 범위 옵션이 없습니다)yash
- 다른 셸에서는 항상
[ -e "$i" ] || [ -L "$i" ] || continue
루프에 추가하여 파일이 존재하는지 확인할 수 있습니다.
답변2
ls
결과를 구문 분석하지 않음, John1024의 답변 외에도 find
.
LC_ALL=C find . ! -name . -prune ! -name '.*' -type f -exec mv -t /path/to/dest {} +
(이것은 GNU find
옵션이 사용되어 glob 과 -t
같은 숨겨진 파일을 건너뛰고 비정규 파일을 제외한다고 가정합니다. 목록은 정렬되지 않습니다( 또는 반대로 ). 이름이 이들로 시작하는 모든 파일은 올바르게 건너뛰어야 합니다 . 사용자의 로케일 유효한 문자에는 포함되지 않지만 이는 오류 메시지의 언어에 영향을 미칩니다.ls
*
ls
*
LC_ALL=C
.