如何根据bash脚本中的命令行参数命名输出文件?

时间:2013-05-31 22:28:02

标签: bash terminal

这些行在复制粘贴到shell时起作用,但在脚本中不起作用:

ls -l file1 > /path/`echo !#:2`.txt
ls -l file2 > /path/`echo !#:2`.txt

ls -l file1 > /path/$(echo !#:2).txt
ls -l file2 > /path/$(echo !#:2).txt

在bash脚本中执行此操作的语法是什么?

如果可能,我想知道如何为一个文件和文件夹中具有相同扩展名的所有文件执行此操作。

2 个答案:

答案 0 :(得分:3)

非交互式shell已禁用历史记录扩展。

在脚本中添加以下两行以启用它:

set -o history
set -o histexpand

答案 1 :(得分:1)

(更新:我误解了原来的问题是指脚本的参数,而不是脚本中当前命令的参数;这是一个重写的答案。)

正如@choroba所说,默认情况下在脚本中禁用历史记录,因为在脚本中执行此类操作并不是正确的方法。

在脚本中执行此类操作的首选方法是将有问题的项目(在本例中为文件名)存储在变量中,然后在命令中多次引用它:

fname=file1
ls -l "$fname" > "/path/$fname.txt"

请注意,您应该几乎总是将变量引用放在双引号内(如上所述),以避免在包含空格或其他shell元字符时出现问题。如果要对多个文件执行此操作,请使用for循环:

for fname in *; do   # this will repeat for each file (or directory) in the current directory
    ls -l "$fname" > "/path/$fname.txt"
done

如果你想对当前目录以外的某个文件进行操作,事情就会复杂一些。您可以使用/inputpath/*,但它将包含路径以及每个文件名(例如,它使用“/ inputpath / file1”,“/ inputpath / file2”等运行循环),如果您使用直接在输出重定向中,您将获得类似> /path/inputpath/file1.txt的内容(即两个不同的路径将被附加在一起),可能不是您想要的。在这种情况下,您可以使用basename命令去除不需要的路径以进行输出:

for fpath in /inputpath/*; do
    ls -l "$fpath" > "/path/$(basename "$fpath").txt"
done

如果您需要具有特定扩展名的文件列表,请根据需要使用*.foo/inputpath/*.foo。但是,在这种情况下,您将最终输出到名为eg的文件。 “file1.foo.txt”;如果您不想要堆叠扩展程序,basename也可以选择修剪它:

for fpath in /inputpath/*.foo; do
    ls -l "$fpath" > "/path/$(basename "$fpath" .foo).txt"
done

最后,它可能更整洁(取决于实际操作的复杂程度,以及它是否在脚本中多次出现)将它包装在一个函数中,然后使用它:

doStuffWithFile() {
    ls -l "$1" > "/path/$(basename "$1" "$2").txt"
}

for fpath in /inputpath/*.foo; do
    doStuffWithFile "$fpath" ".foo"
done
doStuffWithFile /otherpath/otherfile.bar .bar