带有 ls $variable 的 bash 脚本

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/5859012/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-17 23:54:27  来源:igfitidea点击:

bash script with ls $variable

bash

提问by geekmagii

I'm trying to get my script to ls all the files in the form "$variable".*

我试图让我的脚本以“$variable”的形式显示所有文件。*

the parameter is always a file with the extension .001 I want to find all the files with the same name but different extension, eg $file.002, file.003 etc. eg.:

参数始终是扩展名为 .001 的文件我想找到所有具有相同名称但扩展名不同的文件,例如 $file.002、file.003 等,例如:

first=""
others=${first%.001}
ls $others"*"

My problem is the file is named file[success].mpg.001and what gets fed to ls is file[success].mpg*which gives me ls: cannot access file[success].mpg*: No such file or directorybecause lsneeds to see:

我的问题是文件被命名为file[success].mpg.001,哪些被输送到LS是file[success].mpg*这给了我 ls: cannot access file[success].mpg*: No such file or directory,因为ls需要看到:

file\[success\].mpg*

I've been trying everything, the one thing I did notice is ls fed the parameter $1 works, but not if fed $file after I've done file=$1 . So I guess how do I change the variable into a parameter?

我一直在尝试一切,我注意到的一件事是 ls 参数 $1 有效,但如果在我完成 file=$1 后输入 $file 则不行。所以我想如何将变量更改为参数?

回答by bmk

You could use bash's printfcommand to reformat the string. Furthermore you don't need to quote *:

您可以使用bash'sprintf命令重新格式化字符串。此外,您无需引用*

#!/bin/bash
first=""
others=$(printf %q "${first%.001}")
ls $others*

printf %qreformats the string in a format that can be used as shell input (regarding to bash's man page).

printf %q以可用作 shell 输入的格式重新格式化字符串(关于bash的手册页)。

edit regarding to a comment:
The above solution does not work with white spaces in file names. For those cases (as some other answers already mentioned) it's better not to use printfbut to properly quote all variables:

编辑评论
上述解决方案不适用于文件名中的空格。对于这些情况(正如已经提到的其他一些答案),最好不要使用printf而是正确引用所有变量:

#!/bin/bash
first=""
others="${first%.001}"
ls -- "$others"*

回答by Philipp

You should quote the variable, not the wildcard:

您应该引用变量,而不是通配符:

ls -- "$others"*

The double dash stops search for options so that this code should work even if othersbegins with a dash.

双破折号停止搜索选项,因此即使others以破折号开头,此代码也应该工作。

Note that lsis more often than not the wrong solution in scripts. Use it only if you really want to print the list, e.g. in long format:

请注意,这ls通常是脚​​本中的错误解决方案。仅当您确实想打印列表时才使用它,例如长格式:

ls -l -- "$others"*

If you want to print only the names, you don't need lsat all:

如果只想打印名称,则根本不需要ls

echo "$others"*

Unfortunately you cannot use --with echo. If, however, you want an array of the file names, use

不幸的是,您不能使用--with echo。但是,如果您想要一个文件名数组,请使用

filenames=("$others"*)

And should you want to iterate over them, use

如果您想遍历它们,请使用

for filename in "$others"*

回答by Kaleb Pederson

You're not too far off. My first fix is changing line 3 to the following:

你离得太远了。我的第一个修复是将第 3 行更改为以下内容:

ls -- "${others}".*

This will expand $othersand allow the globbing to happen. It's the shells responsibility to expand the *to the list of all matching filenames. The list of filenames is then sent to ls. It sounds like in most cases ls will see something like this:

这将扩大$others并允许发生globbing。扩展*到所有匹配文件名的列表是shell 的责任。然后将文件名列表发送到ls. 听起来在大多数情况下 ls 会看到如下内容:

file1.001 file1.002 file1.003 ...

But, when no files are present, the shell passes the glob to ls and it will see asterisk:

但是,当没有文件存在时,shell 将 glob 传递给 ls,它会看到星号:

file1.*

Thus, your line, ls $others"*"appends a literal asterisk which ls will see.

因此,您的行会ls $others"*"附加一个 ls 会看到的文字星号。

Unless you have a file name file1.*(with a literal asterisks), lswill fail.

除非您有文件名file1.*(带有文字星号),ls否则将失败。

Another option is to use basename:

另一种选择是使用 basename:

first=""
others=`basename -- "$first" .001`
ls -- "${others}".*

Using basenamegives you the advantage that it can remove directories, etc.

使用basename为您提供了可以删除目录等的优势。

However, as others have pointed out, depending on what you're doing with the list of files, findmay be better.

但是,正如其他人指出的那样,根据您对文件列表的处理方式,find可能会更好。

EDIT: The double-hyphen doesn't work on all *nix variants but tells the lsand basenamecommands that no other cli arguments follow. Quoting your variables may be a best practices but I prefer the simplicity of leaving them off unless the data isn't trusted. Know your data and quote appropriately.

编辑:双连字符不适用于所有 *nix 变体,但告诉lsbasename命令没有其他 cli 参数。引用您的变量可能是最佳实践,但我更喜欢将它们保留下来的简单性,除非数据不受信任。了解您的数据并适当引用。

回答by ceving

Use find instead ls:

使用 find 代替 ls:

$ ls weg.*
ls: weg.*: No such file or directory
$ find . -name weg.\*
$