【问题标题】:Bash script to delete and match folder names to partial file names in different directories用于删除文件夹名称并将其与不同目录中的部分文件名匹配的 Bash 脚本
【发布时间】:2012-10-06 11:54:52
【问题描述】:

[编辑] 问题已解决。脚本更新如下。感谢大家的帮助。我需要做一些修改才能使其全部使用文件夹名称和非空文件夹中的空格。

这个真的很难受。

下载文件时,我的系统会创建两件事:

  1. 一个文件(在我的“工作”目录中创建),例如

    • Johns.Pizza.Place.5489231.job
    • Marks.Hair.Salon.NY.888.job
    • Rachels.Bike.and.Boat.Shop.11122287865.job
  2. 带有文件名的文件夹(在我的“Temp”目录中创建),例如

    • Johns.Pizza.Place
    • Marks.Hair.Salon.NY
    • Rachels.Bike.and.Boat.Shop

如您所见,文件夹名称总是与文件名的一部分匹配,但每个文件总是附加一个随机长度的数字,然后是扩展名(即“.job”)。

我想要做的是能够运行一个脚本来尝试

  1. 匹配文件目录中的文件夹名称但仅进行部分匹配,因为文件同时添加了随机数和扩展名,然后

  2. 在未找到关联文件时删除这些文件夹(我在某些操作后使用 Hazel 删除文件)。如果找到一个文件夹的匹配文件,我不希望删除该文件夹。

这是我尝试过的,但我知道它不完整。显然,我试图仅在路径中提取文件夹名称以匹配已删除扩展名的部分文件名,但我不确定如何删除随机数字符串。

[编辑]:下面的最终工作脚本

#! /bin/sh

MainDir="/Users/Dhy/Desktop/Temp Files/1. All Files/"
JobDir="/Users/Dhy/Documents/All Jobs/"                             

find "$MainDir"* -maxdepth 0 -type d | while read FolderName; do
SuffixName=$(basename "${FolderName}");
    preserve=''
    for file in "$JobDir"*.job; do
        if [[ $file\.[0-9]+ =~ $SuffixName ]]; then 
            preserve='on'
        break 
        fi
    done

    if [ -z $preserve ]; then
        rm -rf "$MainDir$SuffixName"
    fi
done

非常感谢任何帮助。

【问题讨论】:

  • 您应该使用#!/bin/bash 而不是#!/bin/sh,因为sh 不支持[[ ]]/bin/sh 可能与 /bin/bash 相关联,但最好小心。

标签: bash shell compare pattern-matching


【解决方案1】:

您对 %% 的使用是删除第一个点之后的所有内容,而不是最后一个点。像这样的东西可能就是你想要的转换:

name="${file%.*.job}"

% 操作符是非贪婪的,所以它会选择最短的匹配字符串来删除。

【讨论】:

  • 谢谢布赖恩。但是仍然有一个问题,包括我的脚本中的问题。那么我不会使用:'for file in *.job;做'部分?
  • 这是为了替代现有的 name= 语句;脚本中的任何其他内容都不应更改。
【解决方案2】:

你可以这样做:

for Dir in $(find $MainDir* -maxdepth 0 -type d ); do
    FolderName=$(basename $Dir);
    cd /Users/Dhy/Documents/Jobs
    if [ -z "$(find . -regex "\./$FolderName\.[0-9]*\.job")" ]
         rmdir "$FolderName"
    fi
done

【讨论】:

  • 谢谢。我觉得它很接近,但一揽子查找命令本质上是查找文件夹名称本身作为匹配项,因此每次都删除。我需要的是“查找”搜索存储在“临时”目录中的文件夹的名称,这些文件夹的名称与不同目录(“作业”目录)中文件的文件名匹配。
  • 对不起。我忘了放置cd 命令=/。这样能解决问题吗?
  • 嗯。不。似乎 find 不服从 cd 文件夹,而是仍在检查自身,因此总是返回 true。必须以不同的方式在第二个目录上运行该 if 语句......但无法弄清楚。
  • find 将始终返回 true (AFAIK),但其输出生成的字符串不应为空(我们使用 -z 标志进行测试)。如果它仍然不起作用,接下来尝试对目录进行硬编码:if [ -z "$(find /Users/Dhy/Documents/Jobs -regex "/Users/Dhy/Documents/Jobs/$FolderName\.[0-9]*\.job")" ]
  • 首先,Janito,感谢您的耐心等待。我试过你的建议,但它似乎仍然不起作用。两个厘米。 1)我在 if 语句的末尾添加了一个“then”,并且我还使用 echo 命令来测试而不是 rmdir。我正在使用一个匹配的文件名和文件夹名,然后我有另一个没有关联文件的文件夹。然而,当脚本运行时,两个文件夹名都表示它们是匹配的,即使在另一个目录中没有具有相同文件夹名的对应文件。
【解决方案3】:

如果您绝对确定实际文件名不包含数字,您可以将name=${file%%[.]*} 替换为name=${file%%.[0-9]*}

同样在您当前的脚本中,只要第一个nameFolderName 不匹配,您就删除该目录。正确的做法是检查所有 names 是否不匹配,即仅在内部 for 循环结束后删除目录。如果匹配,设置一个标志(在下面的情况下,一个非空字符串)以防止目录被删除。

这是我的想法:

#!/bin/bash

MainDir="/Users/Dhy/Desktop/Temp/"
JobDir="/Users/Dhy/Documents/Jobs/"

for Dir in $(find $MainDir* -maxdepth 0 -type d ); do
    FolderName=$(basename $Dir);
    preserve=''
    for file in $JobDir*.job; do
        if [[ $file =~ $FolderName\.[0-9]+ ]]; then 
            preserve='on'
            break 
        fi
    done

    if [ -z $preserve ]; then
       rmdir $MainDir$FolderName
    fi
done

p/s:. 不是参数扩展中的特殊字符,所以可以不带方括号使用。

p/s2:这里不需要cd,只需将路径追加到*即可

【讨论】:

  • 谢谢 DD。这对我来说很有意义,因为我确实需要根据所有文件名检查第一个文件夹。我试过你的脚本,但仍然遇到同样的问题。即使存在具有相同文件名但扩展名为 .job 的相应文件,也会删除所有文件夹。由于某种原因,FolderName 与文件名的匹配要么没有发生,要么被忽略。好奇怪。
  • Awww 打错字了...我忘了使用我建议的name=${file%%.[0-9]*}。现在可以用了吗?
  • 不幸的是它没有。我尝试了一堆不同的排列,但还没有任何效果。
  • 再一次,我在if [ -z $preserve ] 之后错过了then...不确定它是否会改变什么...
  • 实际上我发现了问题所在:$JobDir 被附加到内部 for 循环中的文件名,因此 $FolderName$file 从未匹配。无论如何,这个编辑后的版本现在应该可以工作了。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-04-28
  • 2015-08-24
  • 2019-11-11
  • 1970-01-01
  • 2022-10-15
  • 2012-06-26
相关资源
最近更新 更多