cp의 대화형 옵션을 사용하여 stdin에서 텍스트 저장

cp의 대화형 옵션을 사용하여 stdin에서 텍스트 저장

대화형 쉘 스크립트에서 명령의 출력을 파일에 저장하고 싶습니다.

$ echo "Hello, World" > test.txt

그러나 test.txt가 이미 존재하는 경우 덮어쓰지 않도록 하십시오. 그래서 활용하면 좋을 것 같아요CP그것과의 상호작용 옵션(CP-i) 대상 파일이 존재하는지 확인하십시오. 나는 이것을 시도했습니다 :

$ echo -n "Hello" | cp -i /dev/stdin test.txt 

test.txt가 아직 존재하지 않으면 test.txt에 "Hello"가 기록되지만, test.txt가 존재하면 cp는 이 파이프에서 덮어쓰기 응답만 읽기 때문에 복사가 중단됩니다.

그러나 이

$ cp -i <(echo "World") test.txt
cp: overwrite 'test.txt'? y
'/proc/self/fd/11' -> 'test.txt'

예상대로 작동합니다. cp는 하위 프로세스의 파일 설명자를 소스로 사용하여 test.txt에 cp'ied하는 것 같습니다. 이유는 전혀 모르겠습니다.

어떤 아이디어, 설명 또는 더 나은 방법이 있습니까?

답변1

대신 다른 파일 설명자를 사용하세요./dev/stdin

echo Hello | { cp -i /dev/fd/5 test.txt 5<&0 </dev/tty; }

또는 yes(1)을 통해 스크립트를 작성할 수도 있습니다.

{ echo Hello | { cp -i /dev/fd/5 test.txt 5<&0 <&4; }; } 4<&0

두 가지 변형 중에서 비표준 문제를 해결하려면 zsh에서만 추가 { ... }서라운드가 필요합니다.cp -i ...여러 운영 체제특징.

이는 /dev/fd/N모든 표준 쉘 및 파일을 지원하는 모든 시스템에서 작동해야 합니다. 단, Linux + ksh93 조합은 제외됩니다. 이는 ksh93이 Linux에서 열 수 없는 파이프를 구현하기 위해 Unix 소켓을 사용하기 때문에 작동하지 않습니다 ( 작동 /dev/fd/N할 수도 없음) echo | cat /dev/stdin).

거기에 파일을 넣지 않으면 echo -n "Hello" | cp -i /dev/stdin test.txt실제로 파일이 손상됩니다. 이것이 당신이 그것에 의존해서는 안되는 이유 중 하나입니다."Hello""You suck!"cp -i

답변2

이와 같은 쉘은 bash이미 리디렉션을 통해 파일을 덮어쓰는 것을 방지합니다.

set -o noclobber
echo hello >world
echo hello >world
-bash: world: cannot overwrite existing file

재정의하기 전에 사용자에게 물어볼 수 있으려면 noclobber설정 대신 이와 같은 것을 사용합니다.

#!/bin/bash

# Define function sureYN  [<prompt>]  <target>
sureYN() {
    local prompt="$1" target="$2" yn='y'
    [[ -z "$target" ]] && { target="$prompt"; prompt="Overwrite $target"; }

    [[ -f "$target" && -t 0 ]] && read -p "$prompt (y/n)? " yn >&2
    [[ "$yn" =~ ^[Yy] ]]
}

sureYN /tmp/first && cp -fp /etc/hosts /tmp/first
sureYN "Can I replace /tmp/second" /tmp/second && echo this is the second >/tmp/second

관련 정보