Как создать динамическую команду в Bash? - PullRequest
0 голосов
/ 20 сентября 2019

Я хочу иметь команду в переменной, которая запускает программу и задает имя выходного файла для нее в зависимости от количества выходов файлов (для работы с новым файлом каждый раз).

Вот чтоУ меня есть:

export MY_COMMAND="myprogram -o ./dir/outfile-0.txt"

Однако я бы хотел, чтобы это число outfile увеличивалось при каждом выполнении MY_COMMAND.Вы можете предположить, что myprogram создает файл достаточно быстро до следующего вызова.Таким образом, число может быть получено из числа файлов, существующих в каталоге ./dir/.У меня нет доступа для изменения самой моей программы или использования MY_COMMAND.

Заранее спасибо.

Ответы [ 3 ]

1 голос
/ 20 сентября 2019

Учитывая, что вы не можете изменить myprogram - его опция -o всегда будет записывать в файл, указанный в командной строке, и предполагая, что что-то также вне вашего контроля запускает MY_COMMAND так что вы не можете изменить способ вызова MY_COMMAND, у вас все еще есть контроль над MY_COMMAND

В остальной части этого ответа я собираюсь изменить имя MY_COMMAND на callprog в основном потому, что его легче набирать.

Вы можете определить callprog как переменную, как в вашем примере export callprog="myprogram -o ./dir/outfile-0.txt", но вместо этого вы можете написать сценарий оболочки и имя , которое callprog и сценарий оболочки может делать практически все, что вы захотите.

Итак, у вас есть каталог, полный outfile-<num>.txt файлов, и вы хотите вывести на следующий не конфликтующий outfile-<num+1>.txt.

Ваш сценарий оболочки может получить числа, перечислив файлы, вырезав только числа, отсортировав их, а затем взяв самое большое число.

Если у нас есть эти файлы в dir:

outfile-0.txt
outfile-1.txt
outfile-5.txt
outfile-10.txt

ls -1 ./dir/outfile*.txt создает список

./dir/outfile-0.txt
./dir/outfile-1.txt
./dir/outfile-10.txt
./dir/outfile-5.txt

(с использованием outfile и .txt означает, что это будет работать, даже если есть другие файлы без имени outfile )
Вычистите номер, отправив его через потоковый редактор sed ... захватите номер и сохраните толькота часть:

ls -1 ./dir/outfile*.txt | sed -e 's:^.*dir/outfile-\([0-9][0-9]*\)\.txt$:\1:'

(я использую двоеточие : вместо стандартной косой черты /, поэтому мне не нужно экранировать разделитель каталогов в dir/outfile)

Теперь вам просто нужно выбрать наибольшее число.Сортируйте числа и возьмите верхнюю

| sort -rn | head -1

Сортировка с помощью -n является числовой, а не лексикографической сортировкой, -r переворачивает, поэтому наибольшее число будет первым , а не последним.

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

high=$(ls -1 ./dir/outfile*.txt | sed -e 's:^.*dir/outfile-\([0-9][0-9]*\)\.txt$:\1:' | sort -rn | head -1)

В оболочке (я использую bash) вы можете сделать это на математике, $[high + 1], так что если high равно 10, выражение выдает 11
Вы можете использовать это как числовую часть вашего имени файла.

Весь сценарий оболочки тогда просто должен использовать это число в имени файла.Вот, с разбитыми линиями для лучшей читабельности:

#!/bin/sh

high=$(ls -1 ./dir/outfile*.txt \
       | sed -e 's:^.*dir/outfile-\([0-9][0-9]*\)\.txt$:\1:' \
       | sort -rn | head -1)

echo "myprogram -o ./dir/outfile-$[high + 1].txt"

Конечно, вы бы не echo myprogram, вы просто запустили бы ее.

0 голосов
/ 20 сентября 2019

Вы можете попробовать экспортировать функцию для MY_COMMAND для запуска.

next_outfile () {
    my_program -o ./dir/outfile-${_next_number}.txt
    ((_next_number ++ ))
}

export -f next_outfile
export MY_COMMAND="next_outfile" _next_number=0

Это зависит от "частной" глобальной переменной _next_number, которая инициализируется в 0 и не модифицируется иначе.

0 голосов
/ 20 сентября 2019

вы можете сделать это в функции bash под вашим .bashrc, используя wc для получения количества файлов в директории, а затем добавив 1 к результату

yourfunction () {
dir=/path/to/dir
filenum=$(expr $(ls $dir | wc -w) + 1)
myprogram -o $dir/outfile-${filenum}.txt
}

это должно получить количество файловв $ dir и добавьте 1 к этому номеру, чтобы получить номер, необходимый для имени файла.если вы поместите его в ваш .bashrc или в .bash_aliases и в исходный код .bashrc, тогда он должен работать как любая другая команда оболочки

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...