Linux 如何在bash中创建动态命令?

Linux 如何在bash中创建动态命令?,linux,bash,shell,sh,Linux,Bash,Shell,Sh,我希望在一个变量中有一个命令,该变量运行一个程序,并根据文件出口的数量指定该程序的输出文件名(每次处理一个新文件) 以下是我所拥有的: export MY_COMMAND=“myprogram-o./dir/outfile-0.txt” 但是,每次执行我的_命令时,我想使这个输出文件的数量增加。您可以假设myprogram在下一次调用之前很快创建了文件。因此,可以从目录/dir/中存在的文件数量中检索该数字。我无权更改我的程序本身或使用MY_命令 提前感谢。您可以在.bashrc下的bash函数

我希望在一个变量中有一个命令,该变量运行一个程序,并根据文件出口的数量指定该程序的输出文件名(每次处理一个新文件)

以下是我所拥有的:

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

但是,每次执行
我的_命令时,我想使这个
输出文件
的数量增加。您可以假设
myprogram
在下一次调用之前很快创建了文件。因此,可以从目录
/dir/
中存在的文件数量中检索该数字。我无权更改我的程序本身或使用
MY_命令


提前感谢。

您可以在.bashrc下的bash函数中执行此操作,方法是使用wc获取目录中的文件数,然后在结果中添加1

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

这将获得$dir中的文件数,并在该数后附加1以获得文件名所需的数字。如果您将它放在.bashrc或.bash_别名和source.bashrc下,那么它应该像任何其他shell命令一样工作,因为您不能更改
myprogram
-它的
-o
选项将始终写入命令行上给定的文件,并且假设您无法控制的东西正在运行
MY_命令
,因此您无法更改调用
MY_命令
的方式,您仍然可以控制
MY_命令

对于这个答案的其余部分,我将把名称
MY_COMMAND
改为
callprog
,主要是因为它更容易键入

您可以将
callprog
定义为变量,如示例中的
export callprog=“myprogram-o./dir/outfile-0.txt”
,但您可以编写一个shell脚本并命名为
callprog
,shell脚本可以执行您想要的任何操作

因此,您有一个满是
outfile-.txt
文件的目录,并且希望输出到下一个非冲突的
outfile-.txt

您的shell脚本可以通过列出文件、只剪切数字、对它们进行排序,然后取最大的数字来获取数字

如果我们在
目录中有这些文件

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:'
(我使用冒号
而不是标准的斜杠
/
,因此我不必在
目录/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)
在shell中(我使用的是bash),您可以对其进行数学运算,
$[high+1]
因此,如果high为10,表达式将生成
11

您可以将其用作文件名的数字部分

整个shell脚本只需要在文件名中使用该数字。在这里,为了更好的可读性,断行:

#!/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"

当然你不会回显我的程序,你只需要运行它。

你可以尝试导出一个函数,让
MY\u命令运行

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

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

这依赖于一个“私有”全局变量
\u next\u number
被初始化为0,并且没有进行其他修改。

为了澄清。。。您不能修改
myprogram
,也不能更改调用
myu命令的方式,但您可以为myu命令提供新的定义?我还假设您不局限于导出MY_命令=…
——您可以根据需要编写一个复杂的shell脚本,并将其命名为MY_命令,或者从MY_命令调用它。您是对的,答案是有效的,尽管我没有给出更多详细信息,但是命令${MY u命令}正在与其他一些我无法控制的参数一起使用。因此,对于您的解决方案,我应该通过
“$@”
将它们传递给程序,这很好,但如果输入有双引号,则可能会导致问题。无论如何,谢谢。这有很多答案:1)创建一个索引文件,2)搜索最后一个,然后增加数量,3)计数文件,添加+1。。。等等你已经试过什么了吗?请告诉我们你已经尝试了什么!我写了一个脚本,它可以找出目录中的文件数,然后运行这个命令。这个函数是个好主意
expr
是不必要的;改用
$(…+1))
。分析
ls
的输出是错误的。
sed
可以写为:
.file-\([0-9]\+\)\.tx..
.file-\([1-9][0-9]*\)\.tx..
;)无论如何,答案是正确的。