你如何将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)
的输出,并在有spaces
, newlines
或tabs
地方将其分开。 这基本上意味着,你正在迭代单词 ,而不是覆盖文件名 。 更糟糕的是,你需要采取每个这些残缺的文件名字,然后把它们当作可能匹配当前目录中的文件名的小块。 所以,如果你有一个文件名,其中包含一个恰好与当前目录中的其他文件名相匹配的字的单词,那么这个单词将消失,所有这些匹配的文件名将代替它!
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/