Вы могли использовать функцию в ударе (или любая оболочка POSIX) как это:
grep() {
if [ -t 1 ] && [ -t 0 ]; then
command grep -n "$@"
else
command grep "$@"
fi
}
[ -t 1 ]
часть использует [
команда (также известный как test
) проверять, связан ли stdout с tty.
[ -t 0 ]
вход стандарта проверок, также, так как Вы указали, чтобы только добавить номера строки если grep
единственная команда в конвейере.
Вы могли сделать:
(set -C && cat < /path/to/src > /path/to/dest)
Это ничего не скопирует кроме содержания файла хотя (не полномочия, владение или разреженность как некоторые cp
реализации делают).
Некоторые cp
реализации, включая GNU cp
, имейте нестандартное -n
переключитесь для не избиения файла, если он существует. но GNU cp
возвраты 0
так или иначе.
Вы могли использовать, если оператор в Вашем сценарии оболочки для тестирования существования файла перед копированием чего-то в него:
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
}
cp
...
– Chris Down
14.11.2012, 04:22
return
вместо exit
. То, что волнует меня, является отсутствием атомарности, т.е. могли бы быть условия состязания, где некоторый другой процесс создает файл между этим сценарием, делающим проверку и этим делающий копию.
– MvG
14.11.2012, 09:04
[ -e "$file" ] || [ -L "$file" ]
если Вы хотите рассмотреть символьные ссылки на несуществующие/недоступные файлы. И обратите внимание, что существует потенциал для состояния состязания там.
– Stéphane Chazelas
14.11.2012, 11:48
mv -n tempfile target
. Проверьте это inode target
соответствует тому, который Вы читаете из tempfile, еще приводите к сбою. Предложенные улучшения?
– dubiousjim
14.11.2012, 13:26
Следующий отрывок оболочки копирует файл, только если цель не существует и возвращает ненулевое состояние, если цель существует.
(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
)
Подробно останавливаясь на моем комментарии к ответу h3rrmiller, и после шаблона отрывка Gilles, вот другой метод создания временной копии, затем перемещая его в место. Я полагаю, что этот метод не уязвим ни для каких условий состязания. Это действительно требует -n
флаг на mv
, который не является частью спецификации POSIX. Однако это, действительно кажется, широко доступно. (Проверенный на реализации 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
)
В Linux можно получить использование inode stat -c'%i' "$tmp"
, но это не портативно.
Вместо того, чтобы проверить inode, другая идея состояла бы в том, чтобы проверить, существует ли файл все еще в пути $tmp
. Если mv -n ...
следовавший затем не должен быть. (Если некоторый другой процесс недавно не создал $tmp
перед проверкой, чтобы видеть, отсутствовало ли это.)
Для эффективности имело бы смысл добавлять проверку если $target
существует в начале стандартной программы. Если мы видим, что это действительно существует, мы можем сразу перестать работать, вместо того, чтобы делать копию, пытаясь переместить его, то, видя, что это перестало работать настолько удаляющий копию. Это оставляют как (легкое) осуществление.