bash 你如何将ls的输出发送到mv?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/937716/
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-09 18:14:21  来源:igfitidea点击:

How do you send the output of ls to mv?

bashcommand-line

提问by lhunath

I know you can do it with a find, but is there a way to send the output of lsto mvin the unix command line?

我知道你可以用它做find,但是是有办法的输出发送lsmv在UNIX命令行?

采纳答案by Alex Martelli

One way is with backticks:

一种方法是使用反引号:

mv `ls *.boo` subdir

Edit: however, this is fragileand notrecommended -- see @lhunath's asnwer for detailed explanations and recommendations.

编辑:然而,这很脆弱推荐 - 请参阅@lhunath 的 asnwer 以获取详细的解释和建议。

回答by lhunath

lsis a tool used to DISPLAY some statistics about filenames in a directory.

ls是用于显示有关目录中文件名的一些统计信息的工具。

It is nota tool you should use to enumerate them and pass them to another tool for using it there. Parsing lsis almost alwaysthe wrong thing to do, and it is bugged in many ways.

不是您应该用来枚举它们并将它们传递给另一个工具以在那里使用它的工具。解析ls几乎总是错的事情,并且它在许多方面窃听。

For a detailed document on the badness of parsing ls, which you should reallygo read, check out: http://mywiki.wooledge.org/ParsingLs

有关解析 ls 的错误的详细文档,您应该真正阅读,请查看:http://mywiki.wooledge.org/ParsingLs

Instead, you should use either globs or find, depending on what exactly you're trying to achieve:

相反,您应该使用 globs 或 find,具体取决于您要实现的目标:

mv * /foo
find . -exec mv {} /foo \;


The main source of badness of parsing lsis that ls dumps all filenames into a single string of output, and there is no way to tell the filenames apart from there. For all you know, the entire lsoutput could be one single filename!

解析不良的主要来源ls是 ls 将所有文件名转储到单个输出字符串中,并且无法区分文件名。据您所知,整个ls输出可能是一个文件名!

The secondary source of badness of parsing lscomes from the broken way in which half the world uses bash. They think formagically does what they would like it to do when they do something like:

解析不良的次要来源ls来自世界上一半的人使用 bash 的破坏方式。for当他们做以下事情时,他们认为神奇地做了他们想做的事情:

for file in `ls`  # Never do this!
for file in $(ls) # Exactly the same thing.

foris a bash builtin that iterates over arguments. And $(ls)takes the output of lsand cuts it apart into arguments wherever there are spaces, newlinesor tabs. Which basically means, you're iterating over words, not over filenames. Even worse, you're asking bask to take each of those mutilated filename words and then treat them as globs that may match filenames in the current directory. So if you have a filename which contains a word which happens to be a glob that matches other filenames in the current directory, that word will disappear and all those matching filenames will appear in its stead!

for是一个 bash 内置函数,它迭代参数。并$(ls)ls任何存在spaces,newlines或 的地方获取 的输出并将其分解为参数tabs。这基本上意味着,您正在迭代words,而不是filenames。更糟糕的是,您要求 bask 获取每个残缺的文件名单词,然后将它们视为可能与当前目录中的文件名匹配的 glob。因此,如果您的文件名包含一个单词,而该单词恰好是匹配当前目录中其他文件名的 glob,则该单词将消失,所有匹配的文件名将取而代之!

mv `ls` /foo      # Exact same badness as the ''for'' thing.

回答by Craig Wright

Not exactly sure what you're trying to achieve here, but here's one possibility:

不完全确定您要在这里实现什么,但这是一种可能性:

The "xargs" part is the important piece everything else is just setup. The effect of this is to take everything that "ls" outputs and add a ".txt" extension to it.

“xargs”部分是重要的部分,其他一切都只是设置。这样做的效果是获取“ls”输出的所有内容并为其添加“.txt”扩展名。

$ mkdir xxx  # 
$ cd xxx
$ touch a b c x y z
$ ls
a  b  c  x  y  z
$ ls | xargs -Ifile mv file file.txt
$ ls
a.txt  b.txt  c.txt  x.txt  y.txt  z.txt
$

Something like this could also be achieved by:

这样的事情也可以通过以下方式实现:

$ touch a b c x y z
$ for i in `ls`;do mv $i ${i}.txt; done
$ ls
a.txt  b.txt  c.txt  x.txt  y.txt  z.txt
$

I sort of like the second way better. I can NEVER remember how xargsworks without reading the man page or going to my "cute tricks" file.

我更喜欢第二种方式。如果不阅读手册页或转到我的“可爱技巧”文件,我永远无法记住xargs是如何工作的。

Hope this helps.

希望这可以帮助。

回答by sybreon

Check out find -exec {}as it might be a better option than lsbut it depends on what you're trying to achieve.

检查一下,find -exec {}因为它可能是更好的选择,ls但这取决于您要实现的目标。

回答by cjs

None of the answers so far are safe for filenames with spaces in them. Try this:

到目前为止,对于包含空格的文件名,没有一个答案是安全的。尝试这个:

for i in *; do mv "$i" some_dir/; done

You can of course use any glob pattern you like in place of *.

您当然可以使用任何您喜欢的 glob 模式来代替*.

回答by Paused until further notice.

You shouldn't use the output of ls as the input of another command. Files with spaces in their names are difficult as is the inclusion of ANSI escape sequences if you have:

您不应将 ls 的输出用作另一个命令的输入。如果您有以下情况,名称中带有空格的文件很难包含 ANSI 转义序列:

alias ls-'ls --color=always'

for example.

例如。

Always use find or xargs (with -0) or globbing.

始终使用 find 或 xargs(带 -0)或通配符。

Also, you didn't say whether you want to move files or rename them. Each would be handled differently.

此外,您没有说明是要移动文件还是重命名它们。每个人都会有不同的处理方式。

edit: added -0 to xargs (thanks for the reminder)

编辑:将 -0 添加到 xargs (感谢提醒)

回答by sunny256

/bin/ls | tr '\n' '
find /path/to/srcdir -type f -print0 | xargs -0 -i% mv % dest/
' | xargs -0 -i% mv % /path/to/destdir/

"Useless use of ls", but should work. By specifying the full path to ls(1) you avoid clashes with aliasing of ls(1) mentioned in some of the previous posts. The tr(1) command together with "xargs -0" makes the command work with filenames containing (ugh) whitespace. It won't work with filenames containing newlines, but having filenames like that in the file system is to ask for trouble, so it probably won't be a big problem. But filenames with newlines could exist, so a better solution would be to use "find -print0":

“ls 的无用使用”,但应该有效。通过指定 ls(1) 的完整路径,您可以避免与之前一些帖子中提到的 ls(1) 别名冲突。tr(1) 命令与 "xargs -0" 一起使命令可以处理包含 (ugh) 空格的文件名。它不适用于包含换行符的文件名,但在文件系统中使用这样的文件名是自找麻烦,所以它可能不会成为一个大问题。但是可能存在带换行符的文件名,因此更好的解决方案是使用“find -print0”:

find . -depth=1 -exec mv {} /tmp/blah/ \;

回答by Don Branson

Backticks work well, as others have suggested. See xargs, too. And for really complicated stuff, pipe it into sed, make the list of commands you want, then run it again with the output of sed piped into sh.

正如其他人所建议的那样,反引号效果很好。另请参阅 xargs。对于非常复杂的东西,将它通过管道传输到 sed,创建您想要的命令列表,然后再次运行它,将 sed 的输出通过管道传输到 sh。

Here's an example with find, but it works fine with ls, too:

这是一个使用 find 的示例,但它也适用于 ls:

http://github.com/DonBranson/scripts/blob/f09d24629ab6eb3ce509d4d3078818430306b063/jarfinder.sh

http://github.com/DonBranson/scripts/blob/f09d24629ab6eb3ce509d4d3078818430306b063/jarfinder.sh

回答by dbr

Just use findor your shells globing!

只需使用find或您的外壳全球化!

mv * /tmp/blah/

..or..

..或者..

$ touch "blah\new|
> "
$ ls | xargs file
blahnew|:                  cannot open `blahnew|' (No such file or directory)

You don't have to worry about colour in the ls output, or other piping strangeness - Linux allows basically any characters in the filename except a null byte.. For example:

你不必担心 ls 输出中的颜色,或其他管道奇怪 - Linux 基本上允许文件名中的任何字符,除了空字节.. 例如:

$ find . -exec file {} \;
./blah\new|
: empty

..but find works perfectly:

..但 find 完美地工作:

myargs=()
# don't push if the glob does not match anything
shopt -s nullglob
myargs+=(myfiles*)

回答by Raman

For more complicated cases (often in a script), using bash arrays to build up the argument list can be very useful. One can create an array and push to it with the appropriate conditional logic. For example:

对于更复杂的情况(通常在脚本中),使用 bash 数组来构建参数列表非常有用。可以创建一个数组并使用适当的条件逻辑推送到它。例如:

Following up on @lhunath's recommendationto use globs or find, push files matching a glob pattern to the array:

按照@lhunath 的建议使用 globs 或 find,将匹配 glob 模式的文件推送到数组:

myargs+=("Some directory")

Push files matching a find to the array: https://stackoverflow.com/a/23357277/430128.

将与 find 匹配的文件推送到数组:https: //stackoverflow.com/a/23357277/430128

Add additional arguments as necessary:

根据需要添加其他参数:

mv "${myargs[@]}"

Use myargsin the invocation of a command like mv:

myargs在调用命令时使用,例如mv

##代码##

Note the quoting of the array myargsto pass array elements with spaces correctly.

请注意数组的引用myargs以正确传递带有空格的数组元素。