2012-06-24 5 views
1

동일한 이름이지만 확장명이 다른 일부 파일이있는 4 개의 디렉토리 (이름 : 영어, 아랍어, 프랑스어 및 러시아어)가 있습니다.같은 이름이지만 확장명이 다른 다른 디렉토리의 파일을 검사하는 방법

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

이 파일이 디렉토리에 존재하지만, 예를 이리저리 그냥 "MyFile23.ar"와 "MyFile23.en"(다른 디렉토리에서 제거되는 것을 알 수있다 어떤 경우에는 다음은 이러한 파일의 예입니다 있다).

내가 원하는 것은이 디렉토리의 파일 이름을 비교하고 모든 디렉토리에 존재하지 않는 파일을 제거하는 것입니다.

어떻게하면됩니까?

+2

'남자 basename' 유닉스에 있다는 점 유의 하시길 바랍니다 더 "확장"없다. 마침표는 다른 문자와 마찬가지로 이름에 유효한 문자이며 이름에는 마침표가 두 개 이상있을 수 있습니다. (슬래시와 NUL은 파일 이름에서 금지되거나 불가능하며 이름은 "."과 ".."가 예약되어 있습니다.) – wildplasser

+0

@wildplasser : 그것은 pedantic입니다. 유닉스는 확장 기능을 가지고 있지 않을 수도 있지만, 유닉스 사용자는 그것들을 다루기 때문에 용어를 사용할 때'\. [^.] + $'을 의미합니다. –

+2

난 상관 없어. 그것은 DOS 사용자들처럼 모든 세계가 8.3 개의 대소 문자를 사용한다고 가정하는 것과 같은 의미입니다. 숨어있는 진짜 문제는 두 개의 점이있는 파일 이름이 소프트웨어 (예 : OP 스크립트)를 혼동시킬 수 있다는 것입니다. – wildplasser

답변

0

당신은 연관 배열을 지원 배쉬 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}을 준수하지 않거나 파일이 있으면 원하는 것을 할 수 없습니다 디렉토리. 검증되지 않은, 다시

#!/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 

:

다음은 배쉬 3 또는 4 작동해야 다른 버전입니다. 이전과 같은 조건에서 또는 잘못된 장소에 파일이있는 경우 (예 : 영국인이 프랑스를 방문하는 경우) 원하는대로 할 수 없습니다. ;-)

0

지정된 확장자를 가진 모든 파일이 처리됩니다. 지정된 디렉토리의 서브 디렉토리는 무시됩니다. 지정된 확장명이 아닌 파일 .extensions는 무시됩니다. 지정된 .extensions로 끝나는 이름의 파일과 지정된 모든 디렉토리에서 나타나지 않는 파일은 제거됩니다.

참고 : 스크립트는 처리중인 디렉토리에 잘못된 파일 확장명을 가진 파일이 없다고 가정합니다. 예를 들어 Rusian 디렉토리에있는 .ar 또는 .en 또는 은 바람직하지 않은 결과를 초래할 수 있습니다.

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" 
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 
+0

awk에서 $ 2를 통해 파일 이름의 공백을 처리하지 않으며 전체 파일 이름을 출력하기 위해 awk를 사용하더라도 공백은 find의'-delete'에 의해 캐치되어 여러 매개 변수로 처리됩니다. 또한,'-name'은'-name'의 인스턴스 당 오직 하나의 패턴 (또는 하나의 파일명)만을 허용합니다. –

+0

요점은 일반적인 해결책이 아닙니다. 그것은 하드 코드 된 이름과 4 디렉토리에만 작동 ...그리고 하나의 파일 이름 만 삭제할 것이라고 지적한 바 있습니다. 나는 공백을 무시하고있다. 요점은 상호 작용에 있습니다. 먼저 관심있는 파일을 나열하는 명령을 작성한 다음 원하는 파일을 나열하십시오. – hipe

관련 문제