Bash의 변환 문제

Bash의 변환 문제

찾기에 래퍼를 사용해 보았지만 다음 문제가 발생했습니다. 예를 들어 일부 디렉터리를 매개 변수로 제공하고 싶지만 마지막 매개 변수는 항상 데이터를 삭제해야 하는 기간을 나타내는 숫자입니다. 예를 들어:

rmoldfiles dir1 dir2 dir3 20

30일이 지난 파일을 삭제해야 합니다.looking at mtime of course

스크립트는 다음과 같습니다.

#!/bin/bash

die()
{
  echo >&2 "$@"
  exit 1
}

usage()
{
  echo >&2 "Usage: $0 [dir1 dir2 dir3] [days old]"
  die
}

if [[ (($# < 1)) || -f "$1" ]]; then
  if [[ -f "$1" ]]; then 
    printf '%s\n' "Please provide a directory"
  fi
  usage
fi 

while (( $# )); do 
  while IFS= read -r -d $'\0' file; do
    printf 'rm %s\n' "$file" 
    sleep 1
  done < <(find "$1" -type f -mtime +$2 -print0)
  shift
done

echo "Done deleting"

질문

디렉토리 는 있지만 shift마지막 매개변수는 아닙니다.

답변1

여러 가지 솔루션.

  1. 마지막 명령줄 인수를 선택합니다.

    args=( "$@" )
    num=${args[-1]}
    args=( "${args[@]:0:${#args[@]} - 1}" )
    

    (그런 다음 이러한 파일을 삭제하는 데 사용됩니다 find "${args[@]}" -type f -mtime "+$num" -print -delete).

  2. 번호를 먼저 입력하세요.

     num=$1; shift
    

    (이는 find "$@" -type f -mtime "+$num" -print -delete파일을 삭제하는 데 사용됩니다).

루프는 처리할 디렉터리가 수백 또는 수천 개 있는 경우에만 필요합니다. 이 경우 find명령을 한 번 호출하는 데 시간이 너무 길어집니다. 그렇지 않으면 반복하지 마십시오. find여러 검색 경로를 사용할 수 있습니다.

rm지연을 삽입하고 이를 명시적으로 사용하고 각 파일에 대해 형식화된 출력을 갖고 싶다면 다음 을 수행하세요.

find "$@" -type f -mtime "+$num" -exec sh -c '
    for pathname do
        printf "Removing %s\n" "$pathname"
        rm -- "$pathname"
        sleep 1
    done' sh {} +

당신이 당신을 찾으면하다디렉터리를 반복해야 합니다(또는 이것이 더 나은 경우).

# Assumes that the arguments are in the order
#      num dir1 dir2 dir3 ...

num=$1
shift

for dir do
    printf 'Processing %s...\n' "$dir"

    find "$dir" -type f -mtime "+$num" -exec sh -c '
        for pathname do
            printf "Removing %s\n" "$pathname"
            rm -- "$pathname"
            sleep 1
        done' sh {} +
done

또는,

# Assumes that the arguments are in the order
#      dir1 dir2 dir3 ... num

args=( "$@" )
num=${args[-1]}
args=( "${args[@]:0:${#args[@]} - 1}" )

for dir in "${args[@]}"; do

    # as above

done

답변2

age 매개변수 앞에 세 개의 디렉터리만 예상하고 제공하므로 무분별하게 반복하지 말고 명시적으로 반복하세요.

for dir in 1 2 3; do
  # work with "$1"
  shift
done

또는 인수가 하나 남았을 때 루프를 중지합니다.

while [ "$#" -gt 1 ]; do
  echo "Work with $1"
  shift;
done

"days" 매개변수는 각 교대조마다 이동하므로 먼저 저장해야 합니다.

days=$4

...루프를 호출하기 전에.

...디렉터리 수에 관계없이 전달을 허용하는 경우:

[ "$#" -gt 1 ] || exit 1
days=${@: -1}
while [ "$#" -gt 1 ]; do
  echo work with "$1" and "$days"
  shift
done

이것은 bash 배열을 가져와서 $@마지막 요소( 로 표시되고 -1수정자로 해석되지 않도록 공백으로 구분됨 :)를 요청한 다음 하나가 남을 때까지(최종 초기 "일") 인수를 하나씩 반복합니다. 논쟁).

답변3

(( $# ))다음 으로 변경하세요 (( $# > 1)).

while (( $# > 1 )); do
  echo "file is: $1"
done

echo "days are: $1"

관련 정보