여러 디렉터리를 지우려면 rm을 사용하세요.

여러 디렉터리를 지우려면 rm을 사용하세요.

배열에 저장된 여러 디렉터리를 지우려고 합니다. 다음은 간단한 예입니다(더 많은 디렉토리가 있습니다).

#!/bin/bash    

$IMAGES_DIR="/Users/michael/scripts/imagefiles"
$BACKUP_DIR="/Users/michael/scripts/imagebackups"

...

array=( $IMAGES_DIR $BACKUP_DIR )
for i in ${array[@]}
do
    if [ "$(ls -A $i)" ]; then     # check that directory has files in it
        rm "$i/"*                  # remove them 
    fi
done

각 디렉토리에 대해 다음과 같은 오류가 발생합니다.

rm: /Users/michael/scripts/imagefiles/*: 해당 파일이나 디렉터리가 없습니다.

답변1

하나의 명령으로 모든 것을 수행하는 것은 어떻습니까?

단일 호출로 파일 존재 확인, 글로빙, 삭제를 캡처할 수 있습니다 find. GNU 버전의 경우 find다음이 있습니다.

for f in "${array[@]}"; do
     find "$f" -type f -delete
done

GNU가 없으면 find다음 호출을 사용하십시오.

find "$f" -type f -exec rm -f {} +

( 전체 디렉토리 계층에서 파일을 지우지 않고 직접 하위 파일만 지우려면 -maxdepth 1앞에 추가하십시오 -type f.)

하지만 잠깐만요, 더 있습니다…

~처럼John1024는 현명하게 지적합니다.배열을 첫 번째 인수로 전달하여 루프를 완전히 중단할 수 있습니다 find.

     find "${array[@]}" -type f -delete

그 이유는 다음과 같습니다.1) find한 번의 실행으로 여러 디렉터리를 검색하고 처리할 수 있습니다.2)쉘은 각 요소(디렉토리)가 별도의 위치 인수가 되도록 배열을 분할합니다 find.

답변2

코드를 다음과 같이 변경하세요.

#!/bin/bash    

IMAGES_DIR="/Users/michael/scripts/imagefiles"
BACKUP_DIR="/Users/michael/scripts/imagebackups"

array=( $IMAGES_DIR $BACKUP_DIR )
for i in "${array[@]}"
do
    if [ "$(ls -A "$i")" ]; then     
        rm "${i:?}"/*                 
    fi
done

실수:

  1. $변수 할당 왼쪽에 배치
  2. $i인용 되지 않음if [ "$(ls -A $i)" ];then
  3. "${var:?}"이를 보장하는 데 사용되며 rm "$i/"*절대로 확장되지 않습니다./*

답변3

옵션을 사용하면 파일 피연산자가 존재하지 않는 경우 유틸리티가 불평하지 않습니다 -f. rm또한 실패 시 종료되지 않습니다.

무엇인가요가능한귀하의 경우에는 숨겨진 이름이 있는 파일이나 디렉터리를 제외하고 하나 이상의 디렉터리가 비어 있으므로 *패턴 끝에 있는 디렉터리는 아무 것도 확장되지 않습니다. 쉘 옵션을 설정하여 *glob이 숨겨진 이름과 일치하도록 할 수 있습니다.bashdotglob

또한 할당에 변수 이름을 사용해서는 안 되며 $토큰화 및 파일 이름 생성(와일드카드)을 방지하려면 큰따옴표 변수 확장이 필요합니다. 실수로 환경 변수나 특수 쉘 변수를 손상시키지 않도록 변수 이름은 소문자여야 합니다.

이러한 요소를 고려한 대체 코드 공식화;

#!/bin/bash    

shopt -s dotglob

images_dir="/Users/michael/scripts/imagefiles"
backup_dir="/Users/michael/scripts/imagebackups"

dirs=( "$images_dir" "$backup_dir" )

for dir in "${dirs[@]}"; do
    rm -f "$dir"/*
done

위의 코드는 디렉터리에서 모든 파일을 삭제하려고 시도합니다. 디렉터리에 하위 디렉터리가 있으면 rm이와 관련된 오류가 발생합니다. 이들도 제거하려면 -rwith 를 사용하십시오 rm.

답변4

rm목표가 폴더 배열의 모든 파일을 삭제하는 것이라면 또 다른 옵션은 다음과 같이 배열을 전달하는 것입니다.

#!/bin/bash    

$IMAGES_DIR="/Users/michael/scripts/imagefiles"
$BACKUP_DIR="/Users/michael/scripts/imagebackups"

# ...

# to preserve whitespaces in path strings, add double quotes around each variable
array=( "$IMAGES_DIR" "$BACKUP_DIR" )

# this appends "/*" to the end of each dirname if you want to delete the contents of the directories
# without deleting the directories themselves
array=( "${array[@]/%//*}" )

# this will spread the array into multiple calls to rm
rm -rf ${array[@]}

한 줄의 예:

rm -rf ${array[@]/%//*}

그러나 폴더도 삭제하려면 다음을 사용할 수 있습니다.

rm -rf ${array[@]}

주목해야 할 차이점B층 용액, while은 find제공된 경로를 찾는 동안 발생하는 모든 오류를 인쇄 rm하지만 이 경우에는 그렇지 않습니다.

편집하다:

~처럼선행경로에 공백이나 쉘 와일드카드가 있으면 이와 같이 배열을 확장하는 것이 위험할 수 있다는 점에 유의하는 것이 중요합니다. 이러한 문자로 인해 배열이 분할되는 것을 방지하려면 배열에 추가하는 변수 주위에 큰따옴표를 추가해야 합니다.

관련 정보