대상이 존재하는 경우 cp가 오류 값을 반환하게 합니다.

대상이 존재하는 경우 cp가 오류 값을 반환하게 합니다.

cp대상 파일이 이미 존재하는 경우 (Linux의 GNU coreutils에서) 0이 아닌 값을 반환하는 방법이 있습니까?
아니면 이 기능을 제공하는 일반적으로 사용되는 다른 작은 유틸리티가 있습니까?

이는 쉘 스크립트에서 실수로 아무것도 잃지 않고 사용자 상호 작용 없이 파일을 자동으로 복사하는 데 유용합니다. 사본을 원본과 비교하면 비슷한 결과를 얻을 수 있지만 더 간단한 해결책이 있기를 바랍니다.

답변1

일부 cp구현(GNU 포함 ) 에는 파일이 있는 경우 파일을 손상시키지 않는 cp비표준 스위치가 있습니다 . -n그러나 GNU는 cp어쨌든 돌아옵니다.0

쉘 스크립트에서 if 문을 사용하여 파일 내용을 복사하기 전에 파일이 존재하는지 테스트할 수 있습니다.

if [ -e /path/to/file ]
  then 
   exit 1
  else
   cp file /path/to/file
fi

또는 기능을 원하면 다음과 같이 사용할 수 있습니다.

function cpa(){ 
 if [ -e "$2" ]
  then 
   exit 1
  else 
   /bin/cp "$1" "$2"
  fi 
}

답변2

다음 셸 조각은 대상이 존재하지 않는 경우에만 파일을 복사하고, 대상이 존재하는 경우 0이 아닌 상태를 반환합니다.

(set -C; : >"$target" && cp -- "$source" "$target")

이는 원자적이지 않습니다. $target파기 시도 후 복사가 시작되기 전에 파일이 생성되면 덮어쓰게 됩니다. 게다가 cp이는 원자적이지 않습니다. 다른 프로세스가 파일이 작성되는 것을 관찰할 수 있습니다. 그러나 모든 동시 작성자가 동일한 전략을 사용하는 경우에는 제대로 작동합니다.

다음의 보다 복잡한 코드 조각은 먼저 임시 복사본을 만든 다음 해당 위치로 이동합니다. 여전히 경쟁 조건이 있습니다. 실행 중이 아닌 관련 없는 프로그램이 개체 파일을 생성할 수 있는 작은 시간 창이 있습니다.

( set -C
  tmp=$(mktemp -p "$(dirname -- "$target")")
  cp -- '$source" "$tmp"
  if : >"$target"; then
    mv -i -- "$tmp" "$target"
  else
    rm -- "$tmp"
    false
  fi
)

답변3

h3rrmiller의 답변에 대한 내 의견을 확장하고 Gilles의 조각 패턴을 따르는 것은 임시 복사본을 만든 다음 제자리로 이동하는 또 다른 방법입니다. 나는 이 접근 방식이 경쟁 조건에 영향을 받지 않는다고 생각합니다. POSIX 사양의 일부가 아닌 -non 플래그가 필요합니다 . mv그러나 널리 사용되는 것으로 보입니다. (GNU 구현과 BusyBox, FreeBSD, OS X에서 검증되었습니다.)

(
  tmp=$(mktemp "${target}.XXXXXX") && # "mktemp -p" doesn't work on BSD
  cp -- "$source" "$tmp" && # you may want to add -p flag
  inode=$(ls -di "$tmp" | cut -d' ' -f1) && # see comment below
  mv -n -- "$tmp" "$target" && # won't overwrite, but doesn't then exit non-0
  if [ "$(ls -di "$target" | cut -d' ' -f1)" != "$inode" ]; then
    rm -- "$tmp"; false
  fi
)

stat -c'%i' "$tmp"Linux에서는 다음을 사용하여 inode를 얻을 수 있습니다.그거 휴대용이 아니잖아.

또 다른 아이디어는 inode를 확인하는 대신 파일이 경로에 아직 존재하는지 확인하는 것입니다 $tmp. mv -n ...성공 하면 없어야 합니다. ( $tmp손실을 확인하기 전에 다른 프로세스가 새로 생성되지 않은 경우.)

$target효율성을 위해 루틴 시작 부분에 존재 여부 확인을 추가하는 것이 좋습니다. 존재한다는 사실을 알게 되면 복사본을 만들고 이동하려고 시도한 후 실패한 것을 확인하고 복사본을 삭제하는 대신 즉시 실패할 수 있습니다. 다음은 (간단한) 연습입니다.

답변4

다음을 수행할 수 있습니다.

(set -C &&  cat < /path/to/src > /path/to/dest)

cp그러나 파일 내용( 일부 구현과 같은 권한, 소유권 또는 희소성 제외) 외에는 아무것도 복사하지 않습니다 .

관련 정보