내 스크립트:
#!/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
명령 대체에 다음을 사용하면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
일치하는 항목이 없으면 패턴이 확장되지 않은 상태로 유지되며 루프는 이를 $name
단일 반복의 값으로 사용합니다.
숨겨진 이름( 문자로 시작하는 파일 이름) 에 관심이 있는 경우 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
).