스크립트의 cp 오류

스크립트의 cp 오류

다음 스크립트를 실행할 때 다음 오류가 발생합니다.

cp: cannot stat ls

스크립트 내용

#!/bin/bash
#make copies of all files in directory
cd /home/don
LIST='ls'
for i in $LIST; do
    ORIG=$i
    DEST=$i.old
    cp $ORIG $DEST
    echo "Copied $i"
done

누군가 문제를 볼 수 있습니까?

답변1

주요 오류 중 하나는 ls명령을 사용하려고 하는데 LIST 변수에 'ls' 문자열만 포함되어 있다는 것입니다. 구문 과 함께 명령 대체를 사용할 수 있습니다 $(command). 이 경우에는 사용하지 않는 것이 좋습니다. 왜냐하면 쉽게 사용할 수 있는 형식으로 정보를 제공하지 않기 때문입니다. 그것은 거의 항상출력을 구문 분석하는 실수ls.

이러한 상황에서는 셸 패턴 일치라고도 하는 셸 패턴 일치를 사용해야 합니다.글로빙.

대신 스크립트에서 다음 방법을 제안합니다.

#!/bin/bash
#make copies of all files in directory
for i in /home/don/* ; do
  if [[ -f $i ]]; then
    orig="$i"
    dest="${i}.old"
    cp "$orig" "$dest"
    echo "Copied $i"
  else
    echo "${i} is not a file"
  fi 
done
  • 이는 쉘 글로빙을 사용하여 디렉토리의 모든 파일을 일치시킵니다. ./* 현재 디렉토리( .)에 있는 모든 것을 의미합니다.
  • if명령문은 일치 항목이 파일인지(디렉토리 및 링크에서는 실패함) 확인하고 파일인 경우 복사 시퀀스를 수행합니다.
  • 시스템 환경 변수는 대문자이므로 변수 이름을 소문자로 변경했습니다. 따라서 원치 않는 이름 충돌을 피할 수 있습니다.

답변2

음, 스크립트에 작은 오류가 있습니다. 네 번째 줄에서는 실행하려고 했습니다.ㅋㅋㅋ따라서 작은따옴표로 묶어서는 안 되며 기호 안에 넣어야 합니다.``. 따라서 스크립트는 다음과 같이 변경됩니다.

LIST=`ls`

위와 같이 스크립트를 업데이트해 보세요.

$(ls)그러나 전혀 사용하지 않는 것이 좋습니다 . 루프 헤더에서 쉘 글로빙을 선호해야 합니다.

for i in *; do

처럼데이비드 앤더슨 씨변수 값에 대한 따옴표와 함께 사용할 수 있다고 아래에 설명되어 있습니다(" $나 ") 그 뒤에 오는 명령문의 경우 파일 이름의 공백으로 인해 문제가 발생할 수 있습니다. 프로세스 대체와 결합된 find를 사용하면 이를 방지할 수 있습니다.

while read l; do
    i=$(basename "$l")
done < <(find . -name '*' -maxdepth 1)

스크립트와 설명이 포함된 자세한 답변은 다음과 같습니다.Mr.Arronical. 앞으로 더 나은 스크립팅을 위해 이 내용을 참고하시기 바랍니다.

답변3

'find' 명령 버전

globs 등을 구문 분석하거나 망칠 find필요 없이 스크립트를 한 줄짜리 명령으로 수행할 수 있습니다 .ls

질문에 따르면 귀하의 목표는 현재 디렉터리에 있는 모든 파일의 복사본을 만드는 것입니다. 이를 위해 적절한 명령은 다음과 같습니다.

find . -maxdepth 1 -mindepth 1 -exec cp {} {}".old" \;

이것이 하는 일은 (현재) 디렉토리 find의 모든 파일에 대해 작동 하고 각 파일별로 호출한다는 것입니다(따라서 ). 재귀적이기 때문에 검색 깊이를 제한해야 하므로 플래그 및 플래그는 검색 결과 중 하나로 나열되지 않도록 하는 것입니다 ..cp\;find-maxdepth-mindepth.

샘플 실행:

$ touch "file one"  "file two"                                                 
$ find . -maxdepth 1 -mindepth 1 -exec cp {} {}".old" \;                       
$ ls -1                                                                        
file one
file one.old
file two
file two.old
$ 

메모: cp여전히 디렉토리에 대해 불평할 것입니다. 이 문제를 처리하는 방법에는 몇 가지가 있습니다.

1) 다음과 같은 -type f플래그를 사용하여 목표인 경우 파일만 필터링할 수 있습니다.find

find . -mindepth 1 -maxdepth 1 -type f -exec cp {} {}".old" \;

2) cp -r 디렉토리 복사에도 사용

find . -mindepth 1 -maxdepth 1 -exec cp -r {} {}".old" \;

Python 원라이너

이것은 find그것보다 약간 더 길지만 여전히 작업을 완료하고 특수 파일 이름에 문제가 없습니다.

python -c 'import shutil; import os;[shutil.copyfile(f,f + ".old") for f in os.listdir(".") if os.path.isfile("./" + f)]'

샘플 실행:

$ touch "test file 1" "testfile 2"
$ python -c 'import shutil;import os;[shutil.copyfile(f,f + ".old")
> for f in os.listdir(".")
> if os.path.isfile("./" + f)]'
$ ls -1  
test file 1
test file 1.old
testfile 2
testfile 2.old
$ 

디렉토리를 포함하려면 다음을 사용하십시오.shutil.copytree(source,destination)

python -c 'import shutil; import os;[shutil.copyfile(f,f + ".old") if os.path.isfile("./" + f) else shutil.copytree(f,f + ".old") for f in os.listdir(".")]'

directory_one.old/이미 존재하는 경우에는 실패합니다.

관련 정보