변수를 ~/directory로 설정하면 확장되지 않습니다.

변수를 ~/directory로 설정하면 확장되지 않습니다.

다음과 같이 tar를 사용하여 간단한 백업 스크립트를 설정하려고 합니다.

#!/bin/bash
TIME=`date +%F_%H-%M`
FILENAME=backup-$TIME.tar.gz
SRCDIR="~/PI/tutos/* ~/scripts/*"
DESTDIR=/media/sf_ubuntuSharedFolder/backups
tar cvpzf $FILENAME $SRCDIR

그러나 $SRCDIR을 사용하면 직접 확장하면 발생하지 않는 tar 오류가 발생합니다.

alex@ALeX-VirtualBox:~$ save
tar: ~/PI/tutos/*: Cannot stat: No such file or directory
tar: ~/scripts/*: Cannot stat: No such file or directory

쉘 변수를 사용하는 데 어떤 문제가 있습니까? 그렇지 않으면 폴더 목록을 한 줄로 tar에 어떻게 전달할 수 있습니까?

답변1

문제는 ~-expansion이 변수가 확장될 때( $SRCDIR따옴표가 없는 변수를 인용하는 경우) 수행되지 않으며, 큰따옴표 안에서(변수를 할당하는 경우) 수행되지 않는다는 것 입니다 SRCDIR.

따옴표가 없으면 $SRCDIR분할+글로브 연산자를 호출하게 됩니다. 즉, 스칼라 $SRCDIR변수( )에 저장된 ~/PI/tutos/* ~/scripts/*문자열을 먼저 $IFS분할(기본값은 공백)한 후 각 단어를 와일드카드, 즉 파일 목록과 일치하도록 확장된 패턴으로 처리합니다.

~홈 디렉토리로 확장되지 않기 때문에 다른 문자처럼 취급되므로 현재 디렉토리의 디렉토리가 될 디렉토리에서 파일을 찾습니다. 귀하의 경우에는 디렉토리가 존재하지 않습니다 ~.~/PI/tutos~

$SRCDIR가장 좋은 방법은 배열을 만들고 할당 시 glob을 확장하는 것입니다.

SRCDIR=(~/PI/tutos/* ~/scripts/*) # ~ and globs expanded at this point
tar cvpzf "$FILENAME" "${SRCDIR[@]}"

Split+glob 연산자를 적용하는 것은 $FILENAME의미가 없으므로 따옴표를 사용하여 비활성화합니다 $FILENAME.

불일치가 있으면 ~/PI/tutos/*그대로 유지되므로 계속 오류가 발생합니다 tar. 이를 방지하려면 다음을 수행할 수 있습니다.

shopt -s nullglob # remove non-matching globs
SRCDIR=(~/PI/tutos/* ~/scripts/*)
if ((${#SRCDIR[@]} != 0)); then
  tar cvpzf "$FILENAME" "${SRCDIR[@]}"
fi

다음을 수행하고 싶을 수도 있습니다.

SRCDIR="$HOME/PI/tutos/* $HOME/scripts/*"
tar cvpzf "$FILENAME" $SRCDIR

변수(예: $HOME)는 큰따옴표로 확장되므로 $HOME전역 문자나 $IFS.

~따옴표가 없고 처음이나 뒤에 있으면 s는 변수 할당에서 확장됩니다 :(그래서 $PATH, ... 와 $LD_LIBRARY_PATH같은 변수 할당에서 작동합니다 PATH=~/bin:~/sbin). 따라서 다음을 수행하고 싶을 수도 있습니다.

SRCDIR=~/PI/tutos/*:~/scripts/* # ~ (not globs) expanded here
IFS=:
tar cvpzf "$FILENAME" $SRCDIR

그러나 위와 마찬가지로 문자(이번에는 홈 디렉토리를 콜론으로 구분된 테이블로 정의하므로 가능성이 낮음 )나 전역 문자가 $HOME포함되어 있으면 작동하지 않습니다 .$IFS:/etc/passwd

관련 정보