IT story

디렉토리를 반복적으로 반복하여 특정 확장자를 가진 파일을 삭제하는 방법

hot-time 2020. 6. 21. 19:25
반응형

디렉토리를 반복적으로 반복하여 특정 확장자를 가진 파일을 삭제하는 방법


디렉토리를 재귀 적으로 반복하고 확장자가 .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

아무데도 못 가니까 코드를 완성하는 데 도움이 필요합니다.


find 그것을 위해 만들어졌습니다.

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

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

(여기에서 이스케이프 처리 된 괄호는 -print0or조항 모두에 적용됩니다 .)

GNU와 * BSD find에도 -delete다음과 같은 동작이 있습니다.

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

없이 find:

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

/tmp/*디렉토리에 /tmp/**/*있는 파일이며 하위 폴더에있는 파일입니다. globstar 옵션 ( shopt -s globstar) 을 활성화해야 할 수도 있습니다 . 따라서 질문의 경우 코드는 다음과 같아야합니다.

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

이를 위해서는 bash ≥4.0이 필요합니다 (또는 zsh없이 shopt -s globstar또는 set -o globstar대신 ksh 사용 shopt -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이미 제안 된 것처럼 더 나은 선택 일 것입니다.


다음은 쉘 ( 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 {} +

Some versions of find (GNU, BSD) have a -delete action which you can use instead of calling rm:

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

This method handles spaces well.

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

Edit, fixes off-by-one

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
}

For bash (since version 4.0):

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

That's all.
The trailing extension ".ext" there to select files (or dirs) with that extension.

Option globstar activates the ** (search recursivelly).
Option nullglob removes an * when it matches no file/dir.
Option dotglob includes files that start wit a dot (hidden files).

Beware that before bash 4.3, **/ also traverses symbolic links to directories which is not desirable.


The following function would recursively iterate through all the directories in the \home\ubuntu directory( whole directory structure under ubuntu ) and apply the necessary checks in else block.

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

There is no reason to pipe the output of find into another utility. find has a -delete flag built into it.

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

The for answers provided will not include files or directories that start with a . the following worked for me:

#/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;
}

Just do

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

The following will loop through the given directory recursively and list all the contents :

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

반응형