如何在bash中列出所有不带扩展名的唯一文件名?

3
我有一个任务,需要将一堆文件从一个目录移动到另一个目录。我需要同时移动所有相同文件名的文件(例如blah.pdf,blah.txt,blah.html等),并且每四分钟可以移动一组这样的文件。我之前有一个简短的bash脚本,在这些时间间隔内只能移动单个文件,但是新的名称要求让我感到困惑。

我的旧脚本如下:
find ./ -maxdepth 1 -type f | while read line; do mv "$line" ~/target_dir/; echo "$line"; sleep 240; done

对于新脚本,我基本上只需要用不带扩展名的唯一文件名列表替换 find ./ -maxdepth 1 -type f。然后我可以用do mv "$line*" ~/target_dir/;替换do mv "$line" ~/target_dir/;

那么,说了这么多,有没有什么好的方法来使用bash脚本获取不带文件名的唯一文件列表?我考虑使用正则表达式来获取文件名,然后将它们放入哈希中以获得唯一性,但我希望有更简单/更好/更快的方法。有什么建议吗?

2个回答

2
一个容忍奇怪命名的文件的单行代码可能是:
find . -maxdepth 1 -type f -and -iname 'blah*' -print0 | xargs -0 -I {} mv {} ~/target/dir

如果文件名可以以多个前缀开头,您可以在查找中使用逻辑运算符。例如,要移动blah.*和foo.*,请使用:

find . -maxdepth 1 -type f -and \( -iname 'blah.*' -or -iname 'foo.*' \) -print0 | xargs -0 -I {} mv {} ~/target/dir

编辑

根据评论更新。

以下是我会这样做:

find ./ -type f -printf '%f\n' | sed 's/\..*//' | sort | uniq | ( while read filename ; do find . -type f -iname "$filename"'*' -exec mv {} /dest/dir \; ; sleep 240; done )

也许需要一些解释:
  • find ./ -type f -printf '%f\n': 查找所有文件并仅打印它们的名称,后跟换行符。如果您不想查找子目录,可以用简单的ls代替;
  • sed 's/\..*//':通过删除第一个点之后的所有内容来剥离文件扩展名。 foo.tarfoo.tar.gz都被转换为foo
  • sort | unique:对刚刚找到的文件名进行排序并删除重复项;
  • (:打开子shell:
    • while read filename:读取一行并将其放入$filename变量中;
    • find . -type f -iname "$filename"'*' -exec mv {} /dest/dir \;:在当前目录中查找(find .)所有以filename值开头的文件(-iname "$filename"'*',这也适用于文件名中包含空格的文件)并对每个文件执行mv命令(-exec mv {} /dest/dir \;
    • sleep 240:睡眠
  • ):子shell的结束。
根据您的要求,将-maxdepth 1作为参数添加到find中。

文件名不一定总是“blah”。那只是一个例子。它们不会被硬编码或预先知道。我需要获取所有唯一文件名的列表。因此,对于一个包含文件“blah.html、blah.txt、foo.jpg、foo.html”的文件夹,它应该输出“blah、foo”,然后我可以将其导入到一个脚本中,4分钟后移动blah和foo*。你明白我的意思吗? - Eli
我会编辑答案并提供另一个一行代码的解决方案,但你已经回答了自己的问题 :) - Giuseppe Cardone
Crud,实际上,我刚试了一下,似乎<code>do mv $line*</code>并不起作用。有什么想法吗? - Eli
我编辑了我的回答,希望这是你正在寻找的解决方案。 - Giuseppe Cardone

0

算了,我太蠢了。有一个uniq命令。傻瓜。新的工作脚本是:

find ./ -maxdepth 1 -type f | sed -e 's/.[a-zA-Z]*$//' | uniq | while read line; do mv "$line*" ~/target_dir/; echo "$line"; sleep 240; done

编辑:忘记关闭代码标签和反斜杠。


1
我非常确定你需要将通配符放在引号外面(即 mv "$line"* ...)才能使其正常工作。此外,您应该排除点文件(即在查找命令中添加 -not -name ".*"),以防止它找到 ".somethingorother" -> "" -> mv ""* ... 这种情况,这将是不好的。 - Gordon Davisson

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接