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

我知道你可以做一个find ,但是有没有办法将ls的输出发送到unix命令行中的mv

一种方法是反引号:

 mv `ls *.boo` subdir 

编辑 :但是,这是脆弱的build议 – 请参阅@ lhunath asnwer详细的解释和build议。

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

不是一个你应该用来枚举它们并将它们传递给另一个工具的工具。 parsingls 几乎总是做错的事情,而且在很多方面都是错误的。

有关parsingls的错误的详细文档,您应该仔细阅读: http : //mywiki.wooledge.org/ParsingLs

相反,你应该使用无论是或find,取决于你到底想要达到什么:

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

parsingls不好的主要来源是ls将所有文件名转储到一个输出string中,除此之外,没有办法告诉文件名。 对于你所知道的,整个ls输出可以是一个单一的文件名!

parsing糟糕的第二个来源来自半世界使用bash的破碎的方式。 他们想要神奇地做他们想做的事情,当他们做一些事情时:

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

for是一个bash内build的迭代参数。 $(ls)接受$(ls)的输出,并在有spacesnewlinestabs地方将其分开。 这基本上意味着,你正在迭代单词 ,而不是覆盖文件名 。 更糟糕的是,你需要采取每个这些残缺的文件名字,然后把它们当作可能匹配当前目录中的文件名的小块。 所以,如果你有一个文件名,其中包含一个恰好与当前目录中的其他文件名相匹配的字的单词,那么这个单词将消失,所有这些匹配的文件名将代替它!

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

不完全确定你想在这里实现什么,但这里有一个可能性:

“xargs”部分是所有其他设置的重要部分。 这样做的效果是将所有“ls”输出并添加一个“.txt”扩展名。

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

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

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

我有点像第二种方式更好。 我永远不会忘记xargs是如何工作的,没有阅读手册页或去我的“可爱的技巧”文件。

希望这可以帮助。

查看find -exec {}因为它可能比ls更好,但这取决于你想要达到的目标。

到目前为止,没有任何答案是安全的,其中包含空格的文件名。 尝试这个:

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

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

您不应该使用ls的输出作为另一个命令的input。 包含ANSI转义序列的文件名称中包含空格的文件比较困难,如果您有以下情况:

 alias ls-'ls --color=always' 

例如。

总是使用find或者xargs(带-0)或者globbing。

另外,你没有说你是否想移动文件或重命名文件。 每个将被处理不同。

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

像其他人所暗示的那样,反引号工作的很好。 也见xargs。 而对于非常复杂的东西,把它变成sed,制作你想要的命令列表,然后再用sed的输出端运行sh。

这里有一个查找的例子,但它也适用于ls:

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

 /bin/ls | tr '\n' '\0' | xargs -0 -i% mv % /path/to/destdir/ 

“无用的ls”,但应该工作。 通过指定ls(1)的完整path,您可以避免与以前某些post中提到的ls(1)的别名冲突。 tr(1)命令与“xargs -0”一起使命令使用包含(ugh)空格的文件名。 它不会使用包含换行符的文件名,但是在文件系统中有类似的文件名是要求麻烦的,所以它可能不是一个大问题。 但是换行符的文件名可能存在,所以更好的解决方法是使用“find -print0”:

 find /path/to/srcdir -type f -print0 | xargs -0 -i% mv % dest/ 

只要使用find或你的炮弹globing!

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

..要么..

 mv * /tmp/blah/ 

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

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

..但find完美的作品:

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

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

跟随@ lhunath build议使用globs或find,将与glob模式匹配的文件推送到数组:

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

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

根据需要添加其他参数:

 myargs+=("Some directory") 

在调用像mv这样的命令时使用myargs

 mv "${myargs[@]}" 

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

 #!/bin/bash for i in $( ls * ); do mv $1 /backup/$1 done 

否则,这是由sybreonfind的解决scheme,并build议不绿色mv ls解决scheme。

你把ls用引号包起来放在mv之后,所以就像这样…

 mv `ls` somewhere/ 

但请记住,如果您的任何文件名中有空格,它将无法正常工作。

而且,这样做会更简单: mv filepattern* somewhere/