파이프를 통해 xargs 찾기는 터미널에서는 작동하지만 쉘 스크립트에서는 작동하지 않습니다.

파이프를 통해 xargs 찾기는 터미널에서는 작동하지만 쉘 스크립트에서는 작동하지 않습니다.

현재 디렉터리의 모든 파일(일부 예외 포함)을 다른 디렉터리로 복사하는 Bash 쉘 스크립트를 작성하려고 합니다. 스크립트는 명령을 작성하여 변수에 저장한 다음 실행합니다. 혼란스러운 부분은 다음과 같습니다. 빌드된 명령이 셸 스크립트에서 실행될 때 " find: paths must precede expression: `|xargs'앞의 공백을 제거하면 |알 수 있습니다"라는 메시지와 함께 실패합니다 find: unknown predicate `-i'. 하지만 빌드하고 실행하라고 명령하면 echo제대로 작동합니다! 더 이상한 점은 echo "$cmd"|bash동일한 오류 메시지와 함께 실패한다는 것입니다!

스크립트( synchronize.sh):

#! /bin/bash

EXCLUDED_FILES=(folder1 file.txt synchronize.sh)
FLAGS='-r'
PROJECT_NAME=project

TARGET_DIR=$HOME/Documents/IDE/$PROJECT_NAME/assets
cmd='find ./* -maxdepth 0'
cmd_end="|xargs -i cp -r {} -t $TARGET_DIR"

for file in ${EXCLUDED_FILES[@]}
do
    cmd+=" ! -name \"$file\""
done

cmd+=$cmd_end

$cmd               #Running the command directly fails
#echo  $cmd        #Yet copying and pasting the output of this command will work just fine
#echo "$cmd"|bash  #Though this inexplicably fails, with the same message as just $cmd

파일이나 폴더 이름에는 공백이나 특수 문자(밑줄 및 마침표 제외)가 없습니다.

답변1

따라서 @KamilMaciorowski가 링크한 답변에서 Bash는 명령이 실행되는 문자열에서 파이프를 다르게 처리한다는 것을 알게 되었습니다. 배선을 바꿔서 문제를 해결했는데 $cmd지금 eval "$cmd"은 잘 작동합니다!

코드 삽입 문제가 발생할 수 있지만 eval이는 이 특정 스크립트와 관련이 없습니다.

답변2

명령에 목록을 로드하는 방법에 대한 좋은 아이디어가 있지만 변수와 명령을 결합하는 더 좋은 방법이 있습니다.

@KamilMaciorowski는 여기에 좋은 배경 정보를 제공했지만 여전히 더 확실한 답변을 찾고 있을 수도 있습니다.여기에서 자세한 내용을 읽으면 printf배열을 명령으로 형식화하는 좋은 예를 볼 수 있습니다.find

귀하의 경우 다음과 같습니다.

find ./* -maxdepth 0 $(printf "! -name %s " $EXCLUDED_FILES) -exec cp -r {} $TARGET_DIR \;

관련 정보