평가 없이 변수에 명령 저장 - Unix

평가 없이 변수에 명령 저장 - Unix

나중에 원격 서버에서 실행할 수 있도록 명령을 변수에 저장하려고 합니다. 별표는 폴더 이름으로 대체되어 변수에 저장됩니다. 나중에 사용할 수 있도록 별표와 동일한 명령이 필요합니다.

스크립트:

#!/bin/bash
cmd="ls -lrt /client/*/ver* /client/*/*/ver*  | grep 299 | tail -1"
echo $cmd

산출:

./script.sh 
ls -lrt /client/folder299/version_1 /client/ifolder299/ifolder/version_a /client/ifolder300/ifolder1/version_b /client/ifolder301/ifolder2/version_c /client/ifolder302/ifolder3/version_d | grep 299 | tail -1

주위를 둘러보았지만 운이 없었습니다. 누군가 명령을 있는 그대로 저장하는 방법을 찾도록 도와줄 수 있습니까?

답변1

명령은 평가되지 않으며 문자열은 그대로 변수에 저장됩니다. 따옴표가 없는 변수를 출력하면 와일드카드 패턴이 확장됩니다.


cmd="ls -lrt /client/*/ver* /client/*/*/ver*  | grep 299 | tail -1"

이는 안전하며 cmd리터럴 문자열로 설정할 수 있습니다 ls -lrt /client/*/ver* /client/*/*/ver* | grep 299 | tail -1. 이 경우 문자열 주위에 큰따옴표와 작은따옴표를 사용하는 것의 차이는 중요하지 않습니다(그러나 정적 문자열이므로 작은따옴표를 사용하겠습니다). 쉘이 문자열에서 확장을 수행할 필요가 없다는 점에서는 중요하지 않습니다. 문자열에 변수 또는 명령 대체가 있는 경우 쉘은 이를 확장하지만 실제로는 아무 작업도 수행하지 않습니다.

때를산출변수 값을 사용하면 echo $cmd와일드카드 패턴이 확장되지만(이런 일이 발생함) 명령은 여전히 ​​실행되지 않습니다.

와일드카드 패턴의 확장을 방지하려면 변수를 큰따옴표로 묶어 확장하세요 "$cmd". 개인적으로 나는

printf '%s\n' "$cmd"

해당 값을 인쇄합니다. 바라보다"왜 printf가 echo보다 나은가요?"왜.

관련된:


또한 구문 분석 중이므로 ls -l(자체안전하지 않음) 그런 다음 번호를 찾으세요.어딘가에출력 에는 ls -l파일 크기 등이 있습니다.

해결하려는 더 큰 문제가 무엇인지 다시 생각해보고 완전히 새로운 질문을 해볼 것을 제안합니다.저것대신에.

경로 이름 목록에서 최근 수정된 일반 파일을 찾으려면 다음을 수행하십시오.

unset newest
for pathname in /client/*/ver* /client/*/*/ver*; do
    if [ -f "$pathname" ] && [ "$pathname" -nt "$newest" ]; then
        newest=$pathname
    fi
done

이는 언급한 파일 이름 globbing 패턴이 확인하려는 이름으로 확장된다고 가정합니다. 또한 문자열이 포함된 파일 이름만 허용하도록 제한합니다 299.

unset newest
for pathname in /client/*/ver* /client/*/*/ver*; do
    if [[ "${pathname##*/}" == *299* ]] &&
        [ -f "$pathname" ] && [ "$pathname" -nt "$newest" ]; then
        newest=$pathname
    fi
done

와일드카드 패턴이 재귀적으로 살펴봐야 하는 디렉터리로 확장되는 경우 다음을 사용하세요 bash.

shopt -s globstar
unset newest
for pathname in /client/*/ver*/** /client/*/*/ver*/**; do
    if [[ "${pathname##*/}" == *299* ]] &&
        [ -f "$pathname" ] && [ "$pathname" -nt "$newest" ]; then
        newest=$pathname
    fi
done

SSH를 통해 이 예제를 실행합니다.

ssh user@host bash -s -O globstar <<'END_SCRIPT'
for pathname in /client/*/ver*/** /client/*/*/ver*/**; do
    if [[ "${pathname##*/}" == *299* ]] &&
        [ -f "$pathname" ] && [ "$pathname" -nt "$newest" ]; then
        newest=$pathname
    fi
done
printf 'Newest file: %s\n' "$newest"
END_SCRIPT

답변2

아마도 옵션 f:

$ touch /tmp/filetmp
$ c="ls /tmp/*"

$ set -f
$ echo $c
ls /tmp/*

$ set  +f
$ echo $c
ls /tmp/filetmp

$ rm /tmp/filetmp
$ unset c

Linux에서 일반적으로 기본 옵션은 +f입니다.

답변3

위와 같이 혼란을 드린 점 사과드립니다.

다음과 같이 명령어를 직접 입력하면 문제를 해결할 수 있습니다.

ssh username@host "ls -lrt /client/*/ver* /client/*/*/ver* | grep $4 | tail -1" 

답변4

명령을 변수에 저장할 때 작은따옴표를 사용하십시오. echo명령에 사용할 때는 큰따옴표를 사용하십시오 .

$ cmd='ls -lrt /var/* /tmp/* /home/* | grep test | tail -1'
$ echo "$cmd"
ls -lrt /var/* /tmp/* /home/* | grep test | tail -1

작은 따옴표와 큰 따옴표의 차이점

관련 정보