使用管道符号将文件传递给mv命令。

我正在尝试从终端移动文件,但只是那些来自grep查询结果的文件。

ls -l | grep -i s02 | mv

完成上述命令的最佳方法是什么?


1你想把文件移动到哪里? - nohillside
2个回答

你可以通过运行来实现这个。
cd directory/containing/the/files
mv *[sS]02* /path/to/target/
对于更复杂的操作,还可以使用find来查找所有相关文件。你问题中的示例也可以写成:
cd directory/containing/the/files
find . -type f -maxdepth 1 -iname '*s02*' -exec mv {} /path/to/target/directory/ \;
值得看一下 man find ,看看还有哪些其他选项可用。

很久以前,有人告诉我正则表达式用于匹配字符串,而通配符用于匹配/生成文件名。 或许,“man 3 glob”命令可能会有所帮助。 - fd0

例如使用bash。给定以下文件
$ ls -1
test1
test2
test3
1)为了避免意外,让我们先来看一下命令。
$ for i in test*; do echo mv $i $i.ext; done
mv test1 test1.ext
mv test2 test2.ext
mv test3 test3.ext
如果这是我们想要的,就执行这些命令。
$ for i in test*; do mv $i $i.ext; done
$ ls -1
test1.ext
test2.ext
test3.ext
适应您的需求来调整路径。 2)可以使用sedxargs。让我们先测试一下。
$ ls -1 test* | sed 'p;s/test/test_/' | xargs -n2 printf "%s %s\n"
test2 test_2
test1 test_1
test3 test_3
如果这是我们想要的,就执行这些命令。
$ ls -1 test* | sed 'p;s/test/test_/' | xargs -n2 mv
$ ls -1
test_1
test_2
test_3
文件名中的空格 如果文件名中包含空格,这些脚本将无法按预期工作。在Unix中,空格被用作分隔符。例如,对于以下文件:
$ ls -1
test 1
test 2
test 3
很明显,下面的命令无法按预期工作。
$ for i in test*; do echo mv $i $i.ext; done
mv test 1 test 1.ext
mv test 2 test 2.ext
mv test 3 test 3.ext
解决方案是将空格从分隔符列表中排除。
$ IFS="`printf '\n\t'`"
并将其添加到应处理带有空格的文件名的命令之前。下面的命令
$ IFS="`printf '\n\t'`"; for i in test*; do mv $i $i.ext; done
正常工作
$ ls -1
test 1.ext
test 2.ext
test 3.ext
下一个选项是引用论据。
for i in test*; do mv "$i" "$i.ext"; done
这样就可以使用丰富多样的Unix过滤器,避免对"find ... -exec ... {}"结构的限制。有关其他限制,请参阅下方的注释。 在macOS上的注意事项: 1) 引用自opengroup.org - 产品标准:命令和实用程序V4 引用如下: 1.4.21 sh 问题31:当调用shell时,环境变量IFS是否被忽略? 回答:是的 原因:规范允许sh命令在调用时忽略IFS环境变量的设置。该变量的设置已被用于破坏使用shell解释对system()和execvp()接口的调用的系统的安全性。 参考:技术标准,Shell和实用程序,第6版,第4章,实用程序,sh,环境变量,IFS。 2) 引用自developer.apple.com - Shell输入和输出 引用块: 您可以通过修改shell变量IFS(内部字段分隔符的缩写)来修改read命令的行为。默认行为是在空格、制表符或换行符处拆分输入。通过更改此变量,... 3) 引用自developer.apple.com - 基本控制语句 - 标准循环 引用块: 在下一个示例中,列表是*.JPG...
#!/bin/sh
for i in *.JPG ; do
    mv "$i" "$(echo $i | sed 's/\.JPG$/.x/')"
    mv "$(echo $i | sed 's/\.JPG$/.x/')" "$(echo $i | sed 's/\.JPG$/.jpg/')"
done
这些脚本如果文件名中有特殊字符可能无法正常工作。请先替换这些特殊字符。参见如何去除特殊字符。有很多文章介绍如何重命名带有空格和其他会引起问题的字符的文件,比如文件名中带有空格导致for循环、find命令出错。在*nix系统中,在处理文件之前,最好摆脱这些字符并将文件名转换为您喜欢的格式(例如重命名文件)。参见修复Unix/Linux/POSIX文件名

这将无法处理类似于 test 1 的文件名以及类似的情况。如果当前目录中存在以 test 开头的文件名,它也不会按照您的期望执行。 - nohillside
重命名并不是必要的,只需要使用能确保\0终止字符串的选项和工具,并小心设置和使用变量即可。请参考http://mywiki.wooledge.org/BashPitfalls和http://mywiki.wooledge.org/BashFAQ :-) - nohillside
1在我看来,摆脱病态文件名并不关心其中的陷阱,即尽快对文件名进行规范化处理,然后再进行后续处理,这样更安全、高效和灵活。只需遵循安全性模块化原则即可。 - Vladimir Botka
1谢谢提供链接,但也许人们应该专注于学习系统的运作方式,而不是它的错误之处。如果Shell脚本或程序在文件名中包含了文件系统(和标准)允许的字符而出现故障,那么这些脚本/程序显然是有问题的,需要修复。 - nohillside
我完全不知道人们应该关注什么。随意测试 rename-file 并报告 问题 - Vladimir Botka
@VladimirBotka 我主要在 macOS 上工作,所以文件名中的空格是一件正常且常见的事情。我认为只要文件主要通过图形界面而不是命令行创建/使用,空格将会普遍存在。 - Gordon Davisson
多年来,我发现当涉及到计算机时,人们往往只会做允许的事情,而不是有意义的事情。由于UNIX允许在文件名中包含空格,最好为空格编写代码。维基百科的列表中确实包括macOS作为UNIX的派生版本。苹果曾表示macOS是建立在稳定可靠的UNIX基础上的。 - historystamp
@Gordon Davisson:问题标记为“Unix”,因此答案不是“macOS”特定的。我已经添加了关于如何处理带有空格的文件名的部分。你说得对,这样的文件名很常见,但这并不意味着我必须在文件名中加入空格。文件名中的空格是由微软创造的另一部分世界。在*nix世界中,没有人会自愿使用它,这一点从可能太晚禁止文件名中的空格中可以清楚地看出。 - Vladimir Botka
@Vladimir Botka 文档在哪里? - historystamp
@historystamp:我们并不矛盾。是的,人们可以做允许的事情。如果有人想在自己的腿上开枪,我无法阻止。是的,最好为空间编码。不过,我的首选仍然是避免使用空格,主要是出于安全考虑。是的,macOS 是 UNIX 的派生版本。UNIX 派生版本之间存在许多差异。请毫不犹豫地适当标记它。(我想知道为何要为文件名中的空格这样明显的荒谬之物辩护。与例如下划线相比,文件名中有空格有何优势呢?) - Vladimir Botka
1@VladimirBotka 文件名中的空格与自然语言相匹配,并且早于Unix,因此这不是微软的问题。基本上,如果您的工具使空格不安全,则说明您使用的工具不好。请使用一个“好”的脚本语言,例如AppleScript、VB、Python、Perl、Tcl、Scheme等,而不是像sh这样的“差劲”语言。 - mmmmmm
@Mark:你提到的sh是个好点子。它是各种系统中常见的shell,Ansible决定将其作为跨平台系统管理的默认shell,并拥有超过1000个模块,包括iosxr_*模块。这很可能是IBM以340亿美元收购红帽的原因之一。不要误解,你不想像我一样使用那些糟糕的工具。 - Vladimir Botka
2很抱歉要说,解决空格问题的方法不是改变IFS的值。解决方法是不要find的结果上使用for循环。使用find ... -exec(结合xargs和/或sh -c)是Unix中处理这类事情的标准方式。 - nohillside
没有所谓的“Unix 的正统方式”。也许这适用于 macOS。Unix 的范式是“工具,不是策略!”顺便说一下,这就是我们从一开始讨论的差异。 - Vladimir Botka
回复:关于“文件名中的空格是一件正常且常见的事情”。记录一下:在Unix系统中,带有空格的文件名被认为是异常的文件名 - Vladimir Botka