Аргументы командной строки с файлами данных - PullRequest
1 голос
/ 26 октября 2010

Если я хочу передать файлы данных программы, как я могу различить тот факт, что они являются файлами данных, а не просто строками имен файлов. По сути, я хочу перенаправить файл, но использую аргументы командной строки, чтобы убедиться, что введенные данные верны.

Я использовал:

./theapp < datafile1 < datafile2 arg1 arg2 arg3 > outputfile

но мне интересно, возможно ли, чтобы это выглядело так:

./the app datafile1 datafile2 arg1 arg2 arg3 > outputfile

Разрешение использования аргументов командной строки.

Ответы [ 2 ]

3 голосов
/ 26 октября 2010

Немного сложно объединить два файла в стандартный ввод таким образом. Лучше было бы:

cat datafile1 datafile2 | ./theapp arg1 arg2 arg3 >outputfile

При bash (как минимум) второе перенаправление ввода переопределяет первое, но не увеличивает его. Вы можете увидеть это с помощью двух команд:

cat <realfile.txt </dev/null # no output.
cat </dev/null <realfile.txt # outputs realfile.txt.

Когда вы используете перенаправление, ваше приложение никогда даже не видит >outputfile (например). Он оценивается оболочкой, которая открывает его и подключает к стандартному выводу процесса, который вы пытаетесь запустить. Вся ваша программа, как правило, будет выглядеть так:

./theapp arg1 arg2 arg3

То же самое со стандартным вводом, об этом позаботится оболочка.

Единственная возможная проблема с этой первой командой, приведенной выше, заключается в том, что она объединяет два файла в один поток, так что ваша программа не знает, где заканчивается первый и начинается второй (если она не может каким-то образом определить это из содержимого файлов). ).

Если вы хотите обработать несколько файлов и знать, какие они есть, существует давняя традиция делать что-то вроде:

 ./theapp arg1 arg2 arg3 @datafile1 @datafile2 >outputfile

и затем открыв ваше приложение и обработав сами файлы. Это больше работы, чем позволить оболочке сделать это.

1 голос
/ 26 октября 2010

С точки зрения вашей программы все аргументы командной строки являются строками, и вы должны решить, представляют ли они имена файлов или нет сами. Есть только два байта, которые не могут появиться в имени файла в Unix: 0x00 и 0x2F (NUL и /). [Я действительно имею в виду байтов . За исключением HFS +, файловые системы Unix совершенно не обращают внимания на кодировку символов, хотя разумные люди, конечно, используют UTF-8.]

Перенаправления оболочки вообще не отображаются в argv.

Однако существует соглашение: обрабатывать каждый элемент argv (за исключением, конечно, argv[0]), который не начинается с тире, как имя файла для обработки в порядке их появления. Вы НЕ должны делать никаких операций удаления кавычек; просто передайте их fopen (или open) как есть. Если строка "-" отображается как элемент argv, обработайте стандартный ввод в этой точке до исчерпания, а затем продолжите цикл по argv. И если строка "--" появляется в argv, обрабатывайте все после этой точки как имя файла, независимо от того, начинается ли оно с тире. (Включая последующие появления "-" или "--").

Может существовать удобный библиотечный модуль или даже языковой примитив, чтобы справиться с этим для вас, в зависимости от того, какой язык вы используете. Например, в Perl вы просто пишете

for (<>) {
   ... do stuff with $_ ...
}

и вы получите все, что я сказал в параграфе "Есть соглашение ..." бесплатно. (Но вы сказали, что C, так что, вы должны сделать большую часть этого самостоятельно. Мне не известна библиотека обработки аргументов для простого C, которая стоит места, которое она занимает на диске. :-()

...