Достаточно интересно, кажется, что ответ может быть: «Это зависит от обстоятельств».
Для ясности: mv
указывается с до
Утилита
mv
должна выполнять действия, эквивалентные функцииrename ()
В спецификации функции переименования говорится:
Эта функция
rename ()
эквивалентна для обычных файлов функции , определенной стандартом ISO C. Его включение здесь расширяет определение , включая действия с каталогами, и определяет поведение , когда новый параметр называет уже существующий файл. Эта спецификация требует, чтобы действие функции было атомарным.
Но последняя спецификация ISO C для rename ()
гласит:
7.21.4.2 Функция
переименовать
Краткое содержание
#include
int rename (const char * old, const char * new); Описание
Функция
rename
вызывает файл имя которой - строка, на которую указываетстарый
, отныне известная под именем , заданным строкой, на которую указываетnew
. Файл с именемстарый
больше не доступен с этим именем.Если файл, названный строкой, на которую указываетnew
, существует до вызова функцииrename
, поведение определяется реализацией.Возвращает
Функция
rename
возвращает ноль, если операция завершается успешно, ненулевое значение в случае неудачи; в этом случае, если файл существовал ранее, он все еще известен под своим исходным именем.
Удивительно, но обратите внимание, что нет явного требования атомарности. Он может потребоваться где-то еще в последнем общедоступном стандарте C, но мне не удалось его найти. Если кто-то может найти такое требование, мы приветствуем правки и комментарии.
См. Также Является ли rename () атомарной?
Согласно странице руководства Linux :
Если
newpath
уже существует, он будет заменен атомарно, поэтому что не существует точки, в которой другой процесс, пытающийся получить доступ кnewpath
, не обнаружит, что он отсутствует. Однако, вероятно, будет окно , в котором обаoldpath
иnewpath
относятся к переименованному файлу .
На странице руководства Linux утверждается, что замена файла будет атомарной.
Тестирование и проверка того, что атомарность может быть очень сложной, однако, если это то, насколько далеко вам нужно зайти. Вам непонятно, что вы имеете в виду, используя «Как я могу проверить, является ли mv атомарным».Вы хотите, чтобы требования / спецификация / документация были атомарными, или вам действительно нужно проверить это?
Также обратите внимание, что выше предполагает , что имена двух файлов операндов находятся в та же файловая система. Я не могу найти стандартного ограничения для утилиты mv
, чтобы обеспечить это.
$ echo 'Unites State | California | UNIX | ABC DE' | sed -E 's/([^ |]+ +[^|]+)( +\||$)/"\1"\2/g'
"Unites State" | California | UNIX | "ABC DE"
|
-E
всегда есть пробел, используйте ERE, в некоторых sed
версиях используется -r
вместо ([^ |] + + [^ |] +)
непробельные, не- |
символы, за которыми следует хотя бы один пробел, а затем не- |
символы (+ \ || $)
вышеуказанный образец, за которым следует хотя бы один пробел, а затем |
или конец строки «\ 1» \ 2
цитата согласно требованию из-за не могу комментировать, отвечаю здесь.
perl -pe 's/\w+\s+\w+/\"$&\"/g'
более простой ответ Джорджа Василиу.
POSIXly:
sed 's/[^ |][^|]* [^|]*[^| ]/"&"/g'
Для учета других пустых символов, кроме пробела ASCII, используйте:
sed 's/[^[:blank:]|][^|]*[[:blank:]][^|]*[^|[:blank:]]/"&"/g'
TAB=`echo 'x' | tr 'x' '\011'`; # tab
SPC=`echo 'x' | tr 'x' '\040'`; # space
s="[$SPC$TAB]"; # whitespace regex
W="[^|$TAB$SPC]"; # building block of a word
echo ' United States | California | UNIX|ABC DE' |
sed -e "s/\($W$W*$s$s*\)\{1,\}[^|][^|]*/\"&\"/g"
В Perl я бы на самом деле использовал split
:
#!/usr/bin/env perl
use strict;
use warnings;
#iterate data block below (use <> for reading STDIN)
while ( <DATA> ) {
#split on whitespace|whitespace
my @fields = split /\s*\|\s*/;
#transform individual fields
for ( @fields ) {
#check if it contains a space
next unless m/\s/;
#if it does, quote
s/(^|$)/\"/g;
}
#print output;
print join " \| ", @fields,"\n";
}
__DATA__
Unites State | California | UNIX | ABC DE
Который выводит:
"Unites State" | California | UNIX | "ABC DE"
Но также справляется с полями, состоящими из нескольких слов.
Упростим это до однострочника, потому что все классные ребята:
perl -F'\s*\|\s*' -lane '/\s/&&s/(^|$)/\"/g for @F;print join " \| ",@F'
Неплохо с Perl:
echo $'Unites State | California | UNIX | ABC DE' |perl -pe 's/[a-zA-Z]+[[:space:]]+[a-zA-Z]+/\"$&\"/g'
"Unites State" | California | UNIX | "ABC DE"