rsync
обычно создает новую версию файла рядом с местом назначения, а затем переключает ее на имя назначения в последний момент, когда оно будет завершено. Новая версия может быть создана либо с использованием дельт, то есть изменений между источником и местом назначения, либо как полная копия. (См. Мой ответ для Более умная передача файлов, чем rsync? , чтобы прояснить это различие.)
Флаг - partial
сообщает rsync
о необходимости сохранения и использования любой частично переданный файл в качестве целевого, если соединение прервано по какой-либо причине. (В противном случае частично переданный файл отбрасывается.) Преимущество этого флага состоит в том, что время и полоса пропускания, потраченные на передачу файла, не тратятся впустую, когда rsync
прерывается и повторяется. Недостатком этого флага является то, что файл, переданный на 90% до прерывания, может быть заменен тем же файлом, переданным только на 10% до прерывания.
Флаг - inplace
указывает rsync
создать целевой файл непосредственно на месте. Это часто менее эффективно по времени, но позволяет избежать одновременного наличия двух полных копий файла назначения в удаленной файловой системе. В общем случае этот флаг использовать не следует.
Бессмысленно говорить о «промежутках между аргументами»; это концепция оболочки.
Работа оболочки состоит в том, чтобы брать целые строки ввода и формировать из них массивы аргументов для запуска команд. Это может включать синтаксический анализ строк в кавычках, расширение переменных, подстановочные знаки файлов и выражения тильды и многое другое. Команда запускается стандартным системным вызовом exec
, который принимает вектор строк.
Существуют и другие способы создания вектора строк. Многие программы разветвляют и выполняют свои собственные подпроцессы -с предопределенными вызовами команд -, и в этом случае никогда не существует такой вещи, как "командная строка". Точно так же графическая оболочка (рабочего стола )может запустить процесс, когда пользователь снова перетащит значок файла и поместит его на командный виджет -, нет текстовой строки для символов «между» аргументами.
Что касается вызванной команды, то, что происходит в оболочке или другом родительском/предшественнике процессе, является частным и скрытым -мы видим только массив строк, который стандарт C указывает, что main()
может принять.
В общем, нет. Разбор командной строки выполняется оболочкой, которая не делает неразобранную строку доступной для вызываемой программы. На самом деле ваша программа может быть выполнена из другой программы, которая создала argv не путем синтаксического анализа строки, а путем программного построения массива аргументов.
Нет, это невозможно, если пробелы не являются частью аргумента.
Команда получает доступ к отдельным аргументам из массива (в той или иной форме в зависимости от языка программирования ), и фактическая командная строка может быть сохранена в файле истории (, если она введена в интерактивной подсказке в оболочка, которая имеет файлы истории ), но никогда не передается команде ни в какой форме.
Все команды в Unix в конечном итоге выполняются одной из exec()
семейства функций. Они принимают имя команды и список или массив аргументов. Ни один из них не принимает командную строку так, как она введена в приглашении оболочки. Функция system()
делает это, но ее строковый аргумент позже выполняется функцией execve()
, которая, опять же, принимает массив аргументов, а не строку командной строки.
В общем, это невозможно, как объяснялось в нескольких других ответах.
Однако оболочки Unix являются обычными программами (, и они интерпретируют командную строку и подставляют ее, то есть расширяют команду перед выполнением fork
и execve
для нее ). См. это объяснение bash
операций оболочки . Вы можете написать свою собственную оболочку(или исправить некоторые существующие свободные программы , например. GNU bash)и использовать его в качестве оболочки (или даже оболочки входа в систему, см. passwd (5)и оболочки (5)).
Например, у вас может быть ваша собственная программа-оболочка, поместившая полную командную строку в какую-нибудь переменную окружения (представьте себе MY_COMMAND_LINE
например)-или используйте любой другой вид inter -связь процесса для передачи командной строки из оболочки в дочерний процесс -.
Я не понимаю, зачем вам это нужно, но вы можете запрограммировать оболочку, ведущую себя таким образом (, но я не рекомендую этого делать ).
Кстати, программа может быть запущена некоторой программой, которая не оболочка (, но которая выполняет fork (2 ), затем execve (2 ),или просто execve
для запуска программы в ее текущем процессе ). В таком случае вообще нет командной строки, и ваша программа может быть запущена без команды...
Обратите внимание, что у вас может быть (специализированная )система Linux без установленной оболочки. Это странно и необычно, но возможно. Затем вам нужно будет написать специализированную программу инициализации , запускающую другие программы по мере необходимости -без использования какой-либо оболочки, но с помощью fork
и execve
системных вызовов.
Читайте такжеОперационные системы :Три простых элементаи не забывайте, что execve
практически всегда является системным вызовом(в Linux, они перечислены в системные вызовы (2 ), см. также введение (2 )), которые повторно инициализируют виртуальное адресное пространство(и некоторые другие вещи )процесса делаю это.
Я просто добавлю то, чего не хватает в других ответах.
См. другие ответы
В программе ничего нельзя сделать, но есть кое-что, что можно сделать в оболочке при запуске программы.
Вам нужно использовать кавычки. Поэтому вместо
./myprog aaa bbb
вам нужно сделать одно из этих
./myprog " aaa bbb"
./myprog ' aaa bbb'
Это передаст программе один аргумент со всеми пробелами. Между ними есть разница: второй буквальный, точно такая же строка, как она выглядит (, за исключением того, что '
нужно набирать как\'
). Первый интерпретирует некоторые символы, но разделяется на несколько аргументов. См. цитирование оболочки для получения дополнительной информации. Так что не надо переписывать оболочку, конструкторы оболочки уже об этом подумали. Однако, поскольку теперь это один аргумент, вам придется делать больше передач внутри программы.
Передать данные через стандартный ввод. Это обычный способ передать большие объемы данных в команду. например.
./myprog << EOF
aaa bbb
EOF
или
./myprog
Tell me what you want to tell me:
aaaa bbb
ctrl-d
(Курсивом выводится программа)
Вы всегда можете указать своей оболочке сообщать приложениям, какой код оболочки приводит к их выполнению. Например, с zsh
, передавая эту информацию в переменной окружения $SHELL_CODE
с использованием хука preexec()
(printenv
, используемого в качестве примера, вы должны использовать getenv("SHELL_CODE")
в своей программе):
$ preexec() export SHELL_CODE=$1
$ printenv SHELL_CODE
printenv SHELL_CODE
$ printenv SHELL_CODE
printenv CODE
$ $(echo printenv SHELL_CODE)
$(echo printenv SHELL_CODE)
$ for i in SHELL_CODE; do printenv "$i"; done
for i in SHELL_CODE; do printenv "$i"; done
$ printenv SHELL_CODE; : other command
printenv SHELL_CODE; : other command
$ f() printenv SHELL_CODE
$ f
f
Все они будут выполнять printenv
как:
execve("/usr/bin/printenv", ["printenv", "SHELL_CODE"],
["PATH=...",..., "SHELL_CODE=..."]);
Разрешение printenv
извлекать код zsh, который приводит к выполнению printenv
с этими аргументами. Что вы хотите сделать с этой информацией, мне не ясно.
С bash
функция, наиболее близкая к zsh
preexec()
, будет использовать его $BASH_COMMAND
в ловушке DEBUG
, но обратите внимание, что bash
выполняет некоторый уровень перезаписи в этом (и, в частности, реорганизованы некоторые пробелы, используемые в качестве разделителя ), и это применяется к каждому (, ну, некоторые команды ), а не вся командная строка, введенная в приглашении (, см. также functrace
опция ).
$ trap 'export SHELL_CODE="$BASH_COMMAND"' DEBUG
$ printenv SHELL_CODE
printenv SHELL_CODE
$ printenv $(echo 'SHELL_CODE')
printenv $(echo 'SHELL_CODE')
$ for i in SHELL_CODE; do printenv "$i"; done; : other command
printenv "$i"
$ printf '%s\n' "$(printenv "SHELL_CODE")"
printf '%s\n' "$(printenv "SHELL_CODE")"
$ set -o functrace
$ printf '%s\n' "$(printenv "SHELL_CODE")"
printenv "SHELL_CODE"
$ print${-+env } $(echo 'SHELL_CODE')
print${-+env } $(echo 'SHELL_CODE')
Посмотрите, как некоторые из пробелов, которые являются разделителями в синтаксисе языка оболочки, были сжаты до 1 и как не всегда полная командная строка передается команде. Так что, вероятно, не полезно в вашем случае.
Обратите внимание, что я бы не советовал делать подобные вещи, так как вы потенциально передаете конфиденциальную информацию каждой команде, как в:
echo very_secret | wc -c | untrustedcmd
передаст этот секрет как wc
, так и untrustedcmd
.
Конечно, вы могли бы сделать то же самое и для других языков, кроме оболочки. Например, в C вы можете использовать некоторые макросы, которые экспортируют код C, выполняющий команду, в среду :
.#include <unistd.h>
#include <stdlib.h>
#include <sys/wait.h>
#define WRAP(x) (setenv("C_CODE", #x, 1), x)
int main(int argc, char *argv[])
{
if (!fork()) WRAP(execlp("printenv", "printenv", "C_CODE", NULL));
wait(NULL);
if (!fork()) WRAP(0 + execlp("printenv", "printenv", "C_CODE", NULL));
wait(NULL);
if (argc > 1 && !fork()) WRAP(execvp(argv[1], &argv[1]));
wait(NULL);
return 0;
}
Пример:
$./a.out printenv C_CODE
execlp("printenv", "printenv", "C_CODE", NULL)
0 + execlp("printenv", "printenv", "C_CODE", NULL)
execvp(argv[1], &argv[1])
Посмотрите, как некоторые пробелы были сжаты процессором C pre -, как в случае с bash. В большинстве, если не во всех языках, объем пространства, используемого в разделителях, не имеет значения, поэтому неудивительно, что компилятор/интерпретатор допускает здесь некоторую вольность с ними.