Bash 스크립트 내에서 다음 명령을 실행하려고 합니다.
rm -rf `ls -t ${FOLDER}/other_folder | awk 'NR>5'`
그리고 나는 다음과 같은 것을 시도하고 있습니다.
RM_CMD="$(rm -rf 'ls -t ${FOLDER}/other_folder | awk NR>5')"
나중에 명령이 실제로 실행되기를 원하는 함수에서 사용됩니다.
여러 변형을 시도했지만 항상 실패합니다. 여기서 올바른 접근 방식은 무엇입니까?
-편집하다-
추가 정보
내가 다음과 같은 것을 시도하면
RM_CMD="rm -rf `ls -t ${FOLDER}/other_folder | awk 'NR>5'`"
명령을 즉시 실행하려고 시도하는 것 같습니다. 이는 제가 의도한 바가 아니지만(나중에 실행하기 위해 올바른 명령을 저장하고 싶습니다) 모든 올바른 값을 가져옵니다. 즉, 아무것도 비어 있지 않습니다.
-편집 2-
다음과 같이 명령을 최대한 분할해 보았습니다.
LS_CMD="ls -t ${FOLDER}/other_folder"
AWK_CMD="awk 'NR>5' ${LS_CMD}"
RM_CMD="rm -rf '${AWK_CMD}'"
하지만 이런 문제가 발생합니다.
+ ssh -t user@server 'rm -rf '\''awk '\''NR>5'\'' ls -t /full/path/to/folder/other_folder'\'''
bash: 5 ls -t /full/path/to/folder/other_folder: No such file or directory
답변1
일반적으로 이와 같은 질문에 대한 대답은 다음을 읽어 보는 것입니다.BashFAQ #50: "변수에 명령을 넣으려고 하는데 복잡한 경우가 항상 실패합니다!". 간략한 요약: 변수는 실행 가능한 코드가 아닌 데이터용이며, 변수에 코드를 넣으려고 하면 온갖 문제가 발생합니다.
하지만 이 경우에는 또 다른 중요한 요소가 있습니다. 를 통해 명령을 실행한다는 것입니다 ssh
. 이는 해당 명령이 원격 시스템으로 전달된다는 의미입니다.데이터로, 원격 컴퓨터의 셸에서 명령으로 구문 분석됩니다. 이는 스크립트(로컬 컴퓨터)의 변수에 명령(데이터)을 저장하는 것이 합리적이라는 것을 의미합니다.
당신이 겪고있는 가장 큰 문제는 역 따옴표를 사용하거나 $( )
작은 따옴표로 묶이지 않은 경우 내부 명령이 즉시 (로컬 컴퓨터에서) 실행되고 그 출력이 다음 위치에 저장된다는 것입니다. 변수. 이를 방지하려면 변수를 정의할 때 관련 문자를 이스케이프 처리하면 됩니다.
RM_CMD="rm -rf \$(ls -t '${FOLDER}/other_folder' | awk 'NR>5')"
$( )
일반적으로 선호되는 역따옴표 대신 역따옴표를 사용했습니다 . 제가 보기엔 당신이 어떤 점에서 작은따옴표와 역따옴표를 혼동한 것 같습니다. 비슷해 보이지만 완전히 다른 효과를 가지고 있습니다. $( )
본질적으로 동일한 작업을 수행하지만 시각적으로 모호하지는 않습니다.
또한 는 로컬 컴퓨터의 변수라고 가정하므로 ${FOLDER}
즉시 확장해야 합니다(그리고 공백이나 다른 셸 메타 문자가 포함된 경우에는 작은따옴표를 추가했습니다). 원격 셸로 확장하려면 \"\${FOLDER|/other_folder\"
대신 사용하세요. 실제로 ${FOLDER}
작은따옴표 자체가 포함되어 있으면 작은따옴표를 넣는 것은 작동하지 않습니다. 이 문제를 해결할 방법이 있지만 여기서는 신경 쓰지 않았습니다.
변수 할당에 작은 따옴표를 사용할 수도 있지만 명령에서 작은 따옴표로 인해 문제가 발생할 수 있습니다 awk
(작은 따옴표로 묶인 문자열에 작은 따옴표를 중첩하는 명확한 방법은 없습니다). ${FOLDER}
로컬 컴퓨터에서 확장합니다 . 이는 혼합 인용으로 해결할 수 있지만 지저분합니다.
마지막으로 변수를 사용할 때는 큰따옴표로 묶어야 합니다.
ssh -t user@server "$RM_CMD"
... 이 특별한 경우에는 문제가 되지 않지만 큰따옴표가 아닌 변수 참조에는 문제가 발생할 수 있는 모든 종류의 것들이 있으므로 일반적으로 큰따옴표를 사용하는 것이 좋습니다.