파일 확장자가 있는 경우 제거

파일 확장자가 있는 경우 제거

스크립팅을 처음 접했습니다. 일부 텍스트 파일이 포함된 디렉터리가 있고 일부 텍스트 파일에는 추가 확장자( )도 포함되어 있습니다( .xfr예: , , ).file1.txtfile2.txt.xfrfile3.txtfile4.txt.xfr

bash 스크립트를 작성하여 디렉터리를 확인하고, .xfr파일에 포함된 경우 파일 이름을 바꾸고(확장자 제거), 결과에 따라 로그 항목을 작성해 보세요.

파일 이름을 바꾸는 스크립트를 작성할 수 있지만 if이 부분과 관련해 어려움을 겪고 있습니다. 이것은 유효한 부분입니다:

#!/bin/bash

for file in ~/Test/Files/*.xfr
do
    mv "$file" "${file%.xfr}"
    echo "$file has been resent" > ~/Test/log.txt
done

를 추가하려면 if이것이 효과가 있을 것이라고 생각했지만 슬프게도 그렇지 않습니다.

#!/bin/bash

if [[ ! -e ~/Test/Files/*.xfr ]]
then
    mv "$file" "${file%.xfr}"
    echo "$file has been renamed" > ~/Test/log.txt
else 
    echo "no files were renamed" ~/Test/log.txt
fi

어떤 도움이라도 대단히 감사하겠습니다.

업데이트: 파일 경로 대신 변수를 사용하도록 스크립트가 업데이트되었으며 이제 다음과 같습니다.

#!/bin/bash

PATH='/home/davrog/Test/Files'
LOG='/home/davrog/Test/log.txt'

for file in $PATH/*.xfr

do

if [ -e $PATH/$file ]
   then
     mv "$file" "${file%.xfr}"
     echo "$(date) $file has been resent"
   else
     echo "$(date) no files were stuck when check was run"
fi

done >>$LOG

이것은 mv 함수를 손상시키는 것 같습니다. 파일 이름을 현재 이름으로 다시 바꾸려고 하기 때문에 의심됩니다. 다른 게시물을 보면 mv 함수가 올바르게 보이는데 어떻게 해결해야 할지 잘 모르겠습니다. 도움을 주셔서 미리 감사드립니다.

답변1

첫 번째 스크립트를 약간 수정하세요.

#!/bin/bash

for file in ~/Test/Files/*.xfr
do
    if [ ! -e "$file" ]; then
        echo 'no files were renamed'
        break
    fi

    mv "$file" "${file%.xfr}"
    echo "$file has been renamed" 
done > ~/Test/log.txt

저는 여기서 두 가지 일을 하고 있습니다.

  1. done로그 파일로 리디렉션하면 반복할 때마다 로그 파일이 잘리므로 루프의 모든 stdout을 리디렉션하도록 끝으로 이동했습니다 .

  2. 패턴이 파일 이름과 일치하지 않으면 기본적으로 확장되지 않은 상태로 유지됩니다. 테스트를 통해 이를 감지 -e하고 특별한 메시지를 출력합니다. 그런 다음 break루프를 종료합니다.

선택하다:

#!/bin/bash

for file in "$HOME/Test/Files"/*.xfr
do
    if [ -e "$file" ]; then
        mv "$file" "${file%.xfr}"
        printf '%s has been renamed\n' "$file"
    else
        echo 'no files were renamed'
    fi   
done >"$HOME/Test/log.txt"

여기서는 흐름을 약간 변경하고 $HOME물결표 대신 사용했습니다(IMHO는 스크립트에서 더 잘 보입니다). 나는 또한 변수 데이터를 출력하는 데 일반적으로 더 안전하기 때문에 printf대신 사용합니다 echo(예: "왜 printf가 echo보다 나은가요?").

/bin/sh위의 두 가지 대안을 모두 실행하는 대신 사용할 수도 있습니다 /bin/bash.

더 많은 "보고서"를 작성하려면 다른 옵션이 있습니다:

#!/bin/bash

shopt -s nullglob

xfr_files=( "$HOME/Test/Files"/*.xfr )

for file in "${xfr_files[@]}"; do
    mv "$file" "${file%.xfr}"
done

printf '%d files renamed\n' "${#xfr_files[@]}"
if [ "${#xfr_files[@]}" -gt 0 ]; then
    printf '\t%s\n' "${xfr_files[@]}"
fi

이는 nullglob쉘 옵션을 설정하며, bash일치하는 항목이 없으면 패턴이 비어 있는 것으로 확장됩니다. 그런 다음 이름이 변경된 파일 수를 기록하고 해당 숫자가 0보다 큰 경우 탭 들여쓰기와 함께 파일 이름도 나열합니다.


업데이트된 질문에서, 변수를 사용합니다 PATH. 이것은 쉘의 유틸리티 검색 경로를 보유하는 변수이므로 :--separated 디렉토리 목록 이외의 다른 것으로 설정하면 쉘이 mv일반적으로 사용되는 다른 도구를 찾지 못할 수 있습니다.

일반적으로 쉘 스크립트에서는 대문자 변수 이름을 사용하지 말고 대신 소문자 또는 대소문자가 혼합된 변수를 사용하십시오. 이렇게 하면 쉘이 사용할 수 있는 중요한 변수를 실수로 덮어쓰는 것을 방지할 수 있습니다.

또한, [ -e $PATH/$file ]테스트는 [ -e "$file" ]경로가 값에 포함되어 있으므로 읽어야 합니다 $file. 이것은 위의 코드에서도 내가 사용하고 있는 것입니다. 모든 변수 확장을 큰따옴표로 묶는 것을 잊지 마세요!

답변2

prename이미 설치되어 있다면 다음과 같이 실행할 수 있습니다.

prename 's/\.xfr$// and print "$_ resended\n"' ~/test/*  >  f.log

관련 정보