내 스크립트:
#!/bin/sh
_directory1="/home/user/test1"
_directory2="test2"
cd "${_directory1}/$_directory2"
for i in *
do
echo "$i"
done
오류는 다음과 같습니다.
./myscript.sh: 6: cd: can't cd to /home/user/test1/test2
내가 뭘 잘못했나요?
답변1
편집 전 원본 코드:
#!/bin/sh
_directory1="~/test1"
_directory2="test2"
for i in $(cd "${_directory1}/$_directory2")
do
echo "$i"
done
물결표(
~
)는 변수와 다르게 동작합니다. 예를 들어, 따옴표 안에 사용하면 홈 디렉터리 경로로 확장되지 않습니다. 스크립트에서는$HOME
물결표를 대신 사용하세요.~
명령줄에서 사용할 수 있는 "단축키"이지만$HOME
스크립트에서는 더 설명적입니다.- 바라보다"큰따옴표 안에서 물결표(~)가 확장되지 않는 이유는 무엇입니까?"에 대해 더 많은 정보를 알고 싶습니다.
cd
루프될 수 있는 출력은 없으므로cd
명령 대체에서 with를 사용해도for
아무런 이점이 없습니다. 불행하게도 루프가 실제로 무엇을 하길 원하는지 명확하지 않기 때문에 신뢰할 수 있는 대체 구현을 제공할 수 없습니다.
편집된 코드가 포함되어 있습니다:
#!/bin/sh
_directory1="/home/user/test1"
_directory2="test2"
cd "${_directory1}/$_directory2"
for i in *
do
echo "$i"
done
이 코드는 다음과 같이 출력됩니다.
"./myscript.sh: 6: cd: can't cd to /test2"
변수 이름의 철자가 틀린 경우 _directory1
(그리고 철자가 틀린 변수는 비어 있고 /test2
디렉터리가 존재하지 않습니다).
그런 다음 오류 메시지를 편집했습니다.다시출력된다고 하세요
./myscript.sh: 6: cd: can't cd to /home/user/test1/test2
이는 단순히 디렉토리가 /home/user/test1/test2
존재하지 않음을 의미합니다. 디렉토리가 다음과 같은 증거를 제공하지 않았습니다.하다존재하므로 우리는 귀하의 시스템이 말하는 것을 믿어야 합니다.
다음은 디렉토리의 내용을 나열하는 스크립트입니다(디렉토리가 존재한다고 가정). 이 코드는 각 파일의 전체 경로 이름을 인쇄합니다.
#!/bin/bash
topdir=$HOME/test1
subdir=test2
printf '%s\n' "$topdir/$subdir"/*
또는,
#!/bin/bash
topdir=$HOME/test1
subdir=test2
shopt -s nullglob
for name in "$topdir/$subdir"/*; do
printf '%s\n' "$name"
done
주어진 패턴이 아무것도 일치하지 않으면 쉘 nullglob
옵션으로 인해 루프가 전혀 실행되지 않습니다. 이 nullglob
옵션이 설정되지 않은 경우 if가 아무것도 일치하지 않으면 패턴은 확장되지 않은 상태로 유지되며 루프는 $name
이를 단일 반복에서 for의 값으로 사용합니다.
dotglob
숨겨진 이름(문자로 시작하는 파일 이름)에 관심이 있는 경우 쉘 옵션( )을 설정해야 할 수도 있습니다 .shopt -s dotglob
.
또는 각 파일 이름의 전체 경로를 인쇄하지 않고
#!/bin/bash
topdir=$HOME/test1
subdir=test2
cd "$topdir/$subdir" || exit 1
printf '%s\n' *
실패하면 exit 1
스크립트가 종료됩니다 cd
.
또는,
#!/bin/bash
topdir=$HOME/test1
subdir=test2
cd "$topdir/$subdir" || exit 1
shopt -s nullglob
for name in *; do
printf '%s\n' "$name"
done
전체 경로가 아닌 파일 이름만 인쇄하려면 다음을 사용하십시오 cd
.
#!/bin/bash
topdir=$HOME/test1
subdir=test2
shopt -s nullglob
for name in "$topdir/$subdir"/*; do
printf '%s\n' "$( basename "$name" )"
# or: printf '%s\n' "${name##*/}"
done
그러면 basename
유틸리티를 사용하여 경로 이름의 파일 이름 부분만 추출됩니다. 주석의 대안은 표준 매개변수 대체를 사용하여 ${name##*/}
파일 이름 앞의 초기 디렉토리 경로를 제거하는 것입니다(문자 그대로 " */
패턴과 일치하는 가장 긴 접두사 문자열을 제거 $name
").