대화형 쉘 스크립트에서 명령의 출력을 다음과 같은 파일에 저장하고 싶습니다.
$ 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 ...
멀티오스특징.
이것은 Linux + ksh93 조합을 제외하고 모든 표준 쉘 및 파일을 지원하는 모든 시스템에서 작동해야 합니다. ksh93은 Linux에서 열 수 없는 (심지어 작동하지도 않는) /dev/fd/N
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