如何检查具有相同名称但扩展名不同的不同目录中的文件

时间:2012-06-24 18:48:52

标签: linux bash text

我有4个目录(名称:英语,阿拉伯语,法语和俄语),其中有一些名称相同但扩展名不同的文件。以下是此类文件的示例:

MyFile104.en
MyFile104.ar
MyFile104.fr
MyFile104.ru

在某些情况下,可以看到某个目录中存在一个文件,但该文件已从其他目录中删除(例如,仅存在“MyFile23.ar”和“MyFile23.en”)。

我想要做的是比较这些目录中的文件名,并删除所有目录中不存在的文件。

我该怎么做?

3 个答案:

答案 0 :(得分:0)

如果你有支持关联数组的Bash 4:

#!/bin/bash
declare -A languages
languages["English"]=en
languages["Arabic"]=ar
languages["French"]=fr
languages["Russian"]=ru

for language in "${!languages[@]}"
do
    for file in MyFile*."${languages[language]}"
    do
        rmflag=false
        for compare in "${!languages[@]}"
        do
            compfile=compare/${file##*/}
            compfile=${compfile%.${languages[language]}}.${languages[compare]}
            if ! $rmflag && [[ ! -e $compfile ]]
            then
                rm "$file"
                rmflag=true
            elif $rmflag && [[ -e $compfile ]]
            then
                rm "$compfile"
            fi
        done
    done
done

如果文件不符合MyFile*.{en,ar,fr,ru}或主目录下有目录,则未经测试,可能无法执行您想要的操作。

这是另一个适用于Bash 3或4的版本:

#!/bin/bash
for dir in English Arabic French Russian
do
    for file in "$dir"/*
    do
        base=${file##*/}
        base=${base%.*}
        files=({English,Arabic,French,Russian}/"$base".{en,ar,fr,ru})
        if (( ${#files[@]} != 4 ))
        then
            rm -f {English,Arabic,French,Russian}/"$base".{en,ar,fr,ru}
        fi
    done
done

再次,未经测试。它可能无法在与以前相同的条件下执行您想要的操作,或者如果文件位于错误的位置(例如英国人正在访问法国)。 ; - )

答案 1 :(得分:0)

处理具有指定扩展名的所有文件。忽略指定目录的子目录。除了指定的文件之外的文件.extensions将被忽略。将删除名称以任何指定的.extensions结尾且未在所有指定目录中出现的文件。

注意:该脚本假定在正在处理的目录中没有文件扩展名错误的文件。例如,.ar目录中的任何.en.frRusian都可能导致不良后果!

langs=( Arabic English French Russian )
extns=( ar en fr ru )
rxext="${extns[@]}" 
rxext="${rxext// /\\|}"  # regex: for .extensions

find "${langs[@]}" -maxdepth 1 -type f -regex ".*\.\($rxext\)$" -printf '%f\n' |
  sed -n "s/\(.*\)\..*$/\1/p" | sort | uniq -c |           # name is in how many dirs?
    sed -n "/^ *${#langs[@]} \(.*\)/!{s/^ *[0-9]\+ //p}" | # names not in all dirs
      xargs -I {} find "${langs[@]}" -maxdepth 1 -type f -regex ".*\/{}\.\($rxext\)$" |
        xargs -I {} rm {}

如果要在给定语言的目录中保留和忽略具有非本机语言扩展名的文件,那么下一个脚本就是这样做的。

all="/tmp/all_${0##*/}"
del="/tmp/del_${0##*/}"

extns=( ar     en      fr     ru      )
langs=( Arabic English French Russian )

# list names (not paths) whose extensions match a given directory
for (( i=0; i<${#extns[@]}; i++ )) do
  find "${langs[i]}" -maxdepth 1 -type f -name "*.${extns[i]}" -printf '%f\n'
done >"$all"

# list names not in all dirs
sed -nr "s/(.*)\..*$/\1/p" "$all" | sort | uniq -c |         # name is in how many dirs?
  sed -nr "/^ *${#extns[@]} (.*)/!{s/^ *[0-9]+ //p}" >"$del" 

# list names in deficit; add paths; then delete files
grep -F -f "$del" "$all" |
  sed -r "$(for (( i=0; i<${#extns[@]}; i++ )) ;do
              echo "s/.*\.${extns[i]}$/${langs[i]}\\/&/;t;"
            done)" | xargs -d "\n" rm

rm "$all" "$del"

答案 2 :(得分:0)

# create test environment
$ for i in ar fr ru en; do mkdir -p $i; touch $i/t1.{fr,en,ru,ar}; done
$ rm en/t1.fr

# print filenames to be deleted (less than 4 occurances)
$ find ar en fr ru  -name t1.'*' | sed 's/^.*\///' | sort | uniq -c | awk '$1!=4{print $2}'

# remove files with less than 4 occurances
$ find ar en fr ru -name $(find ar en fr ru  -name t1.'*' | sed 's/^.*\///' | sort | uniq -c | awk '$1!=4{print $2}') -delete