programing

디렉터리를 반복적으로 순환하여 특정 확장명의 파일을 삭제하는 방법

powerit 2023. 5. 8. 22:28
반응형

디렉터리를 반복적으로 순환하여 특정 확장명의 파일을 삭제하는 방법

으로 반복적으로 반복하고 모든 을 제거해야 합니다..pdf그리고..doc디렉터리를 반복적으로 반복적으로 검색할 수는 있지만 위에서 언급한 파일 확장자를 가진 파일을 필터링할 수는 없습니다.

지금까지의 나의 코드

#/bin/sh

SEARCH_FOLDER="/tmp/*"

for f in $SEARCH_FOLDER
do
    if [ -d "$f" ]
    then
        for ff in $f/*
        do      
            echo "Processing $ff"
        done
    else
        echo "Processing file $f"
    fi
done

코드를 완성하는 데 도움이 필요합니다. 아무 데도 갈 수가 없어서요.

mouviciel의 답변에 대한 후속 조치로, 당신은 이것을 xargs를 사용하는 대신 for 루프로 할 수도 있습니다.저는 특히 각 반복에서 더 복잡한 작업을 해야 할 경우 자주 xargs가 번거롭다고 생각합니다.

for f in $(find /tmp -name '*.pdf' -or -name '*.doc'); do rm $f; done

많은 사람들이 언급했듯이 파일 이름에 공백이 있으면 이 작업은 실패합니다.IFS(내부 필드 구분자)를 임시로 새 줄 문자로 설정하여 이 문제를 해결할 수 있습니다. 문자 " " " " 가 있을 합니다.\[?*파일 이름으로.와일드카드 확장(글로브)을 일시적으로 비활성화하여 이 문제를 해결할 수 있습니다.

IFS=$'\n'; set -f
for f in $(find /tmp -name '*.pdf' -or -name '*.doc'); do rm "$f"; done
unset IFS; set +f

파일 이름에 새 줄이 있으면 해당 줄도 작동하지 않습니다.xargs 기반 솔루션을 사용하면 다음과 같은 이점을 얻을 수 있습니다.

find /tmp \( -name '*.pdf' -or -name '*.doc' \) -print0 | xargs -0 rm

는 (으)로 합니다.)-print0두 가지 모두에 적용됩니다.or절).

GNU *에는 GNU 및 *BSD find에가 있습니다.-delete다음과 같은 동작:

find /tmp \( -name '*.pdf' -or -name '*.doc' \) -delete

find그것을 위해 만들어진 것입니다.

find /tmp -name '*.pdf' -or -name '*.doc' | xargs rm

없이.find:

for f in /tmp/* tmp/**/* ; do
  ...
done;

/tmp/* 및 파이dir에 있는 입니다./tmp/**/*하위 폴더에 있는 파일입니다. 옵션globstar option)을 해야 할 수 .shopt -s globstar질문에 대한 코드는 다음과 같습니다.

shopt -s globstar
for f in /tmp/*.pdf /tmp/*.doc tmp/**/*.pdf tmp/**/*.doc ; do
  rm "$f"
done

에는 bash zsh 없이 zsh)이합니다.shopt -s globstar 는리어울는이 있는 ▁k▁with.set -o globstarshopt -s globstar또한 bash < 4.3에서 이것은 디렉토리뿐만 아니라 디렉토리에 대한 심볼릭 링크를 통과하며, 이는 일반적으로 바람직하지 않습니다.

재귀적으로 무언가를 수행하려면 재귀를 사용하는 것이 좋습니다(예, 스택 등을 사용하여 수행할 수 있지만, 헤이).

recursiverm() {
  for d in *; do
    if [ -d "$d" ]; then
      (cd -- "$d" && recursiverm)
    fi
    rm -f *.pdf
    rm -f *.doc
  done
}

(cd /tmp; recursiverm)

그렇긴 하지만,find이미 제안한 것처럼 더 나은 선택일 수 있습니다.

셸shell)을.bash):

#!/bin/bash

# loop & print a folder recusively,
print_folder_recurse() {
    for i in "$1"/*;do
        if [ -d "$i" ];then
            echo "dir: $i"
            print_folder_recurse "$i"
        elif [ -f "$i" ]; then
            echo "file: $i"
        fi
    done
}


# try get path from param
path=""
if [ -d "$1" ]; then
    path=$1;
else
    path="/tmp"
fi

echo "base path: $path"
print_folder_recurse $path

이것은 당신의 질문에 직접적으로 대답하지는 않지만, 당신은 한 줄로 당신의 문제를 해결할 수 있습니다.

find /tmp \( -name "*.pdf" -o -name "*.doc" \) -type f -exec rm {} +

find(GNU,에는 일부버찾기(GNU, BSD)가 .-delete호출하는 대신 사용할 수 있는 작업rm:

find /tmp \( -name "*.pdf" -o -name "*.doc" \) -type f -delete

bash(버전 4.0 이후)의 경우:

shopt -s globstar nullglob dotglob
echo **/*".ext"

이상입니다.
해당 확장명을 가진 파일(또는 dirs)을 선택하기 위한 뒤에 오는 확장명 ".ext".

globstar 옵션은 **(재귀적으로 검색)를 활성화합니다.
옵션 nullglob은 파일/dir가 일치하지 않는 *를 제거합니다.
옵션 dotglob에는 점으로 시작하는 파일(숨겨진 파일)이 포함됩니다.

bash 4.3 이전에 주의하십시오.**/또한 바람직하지 않은 디렉토리에 대한 심볼릭 링크를 통과합니다.

이 방법은 공백을 잘 처리합니다.

files="$(find -L "$dir" -type f)"
echo "Count: $(echo -n "$files" | wc -l)"
echo "$files" | while read file; do
  echo "$file"
done

하나씩 편집, 수정

function count() {
    files="$(find -L "$1" -type f)";
    if [[ "$files" == "" ]]; then
        echo "No files";
        return 0;
    fi
    file_count=$(echo "$files" | wc -l)
    echo "Count: $file_count"
    echo "$files" | while read file; do
        echo "$file"
    done
}

이것이 제가 아는 가장 간단한 방법입니다.rm **/@(*.doc|*.pdf)

**이 작업을 반복적으로 수행합니다.

@(*.doc|*.pdf)PDF 또는 문서로 끝나는 파일을 찾습니다.

교체하여 안전하게 테스트하기 쉽습니다.rm와 함께ls

다음 함수는 의 모든 디렉터리를 통해 재귀적으로 반복됩니다.\home\ubuntu디렉토리(Ubuntu 아래의 전체 디렉토리 구조) 및 필요한 체크 인을 적용합니다.else블록으로 막다

function check {
        for file in $1/*      
        do
        if [ -d "$file" ]
        then
                check $file                          
        else
               ##check for the file
               if [ $(head -c 4 "$file") = "%PDF" ]; then
                         rm -r $file
               fi
        fi
        done     
}
domain=/home/ubuntu
check $domain

의 출력을 파이프로 연결할 이유가 없습니다.find다른 유틸리티로. find을 가지고 있습니다.-delete내장된 깃발.

find /tmp -name '*.pdf' -or -name '*.doc' -delete

제공된 다른 답변에는 a로 시작하는 파일이나 디렉토리가 포함되지 않습니다. 다음은 저에게 도움이 되었습니다.

#/bin/sh
getAll()
{
  local fl1="$1"/*;
  local fl2="$1"/.[!.]*; 
  local fl3="$1"/..?*;
  for inpath in "$1"/* "$1"/.[!.]* "$1"/..?*; do
    if [ "$inpath" != "$fl1" -a "$inpath" != "$fl2" -a "$inpath" != "$fl3" ]; then 
      stat --printf="%F\0%n\0\n" -- "$inpath";
      if [ -d "$inpath" ]; then
        getAll "$inpath"
      #elif [ -f $inpath ]; then
      fi;
    fi;
  done;
}

가장 간단한 해결책은 재귀를 사용하는 것이라고 생각합니다. 다음 예제에서는 디렉터리와 하위 디렉터리의 모든 파일 이름을 인쇄했습니다.

필요에 따라 수정할 수 있습니다.

#!/bin/bash    
printAll() {
    for i in "$1"/*;do # for all in the root 
        if [ -f "$i" ]; then # if a file exists
            echo "$i" # print the file name
        elif [ -d "$i" ];then # if a directroy exists
            printAll "$i" # call printAll inside it (recursion)
        fi
    done 
}
printAll $1 # e.g.: ./printAll.sh .

출력:

> ./printAll.sh .
./demoDir/4
./demoDir/mo st/1
./demoDir/m2/1557/5
./demoDir/Me/nna/7
./TEST

그것은 공간에서도 잘 작동합니다!

참고: 사용할 수 있습니다.echo $(basename "$i") # print the file name경로 없이 파일 이름을 인쇄합니다.

OR: 사용echo ${i%/##*/}; # print the file name외부에 전화하지 않고도 매우 빠르게 실행됩니다.basename.

그냥 해요

find . -name '*.pdf'|xargs rm

명령을 실행하는 데 사용되는 셸을 변경할 수 있는 경우 ZSH를 사용하여 작업을 수행할 수 있습니다.

#!/usr/bin/zsh

for file in /tmp/**/*
do
    echo $file
done

모든 파일/폴더를 반복적으로 순환합니다.

다음은 지정된 디렉터리를 반복적으로 순환하고 모든 내용을 나열합니다.

for d in /home/ubuntu/*; 
do 
    echo "listing contents of dir: $d"; 
    ls -l $d/; 
done

언급URL : https://stackoverflow.com/questions/4638874/how-to-loop-through-a-directory-recursively-to-delete-files-with-certain-extensi

반응형