파일을 반복하고 일부 작업을 수행하는 스크립트가 있습니다.문자열 교체날짜를 삽입하세요.
#!/bin/bash
f="/tmp/file.txt" # with .txt extension
timestamp="$(date +%H%M%S)"
echo "${f%%.*}-$timestamp.${f#*.}"
다음과 같은 결과가 출력됩니다. 이는 올바른 것입니다.
/tmp/file-220304.txt
그러나 파일에 확장자가 없으면 스크립트가 중단됩니다.
#!/bin/bash
f="/tmp/file" # no extension
timestamp="$(date +%H%M%S)"
echo "${f%%.*}-$timestamp.${f#*.}"
$ ./test.sh
/tmp/file-220359./tmp/file
${f:-not found}
공백을 채우기 위해 정의되지 않은 경우와 같은 것을 사용할 수 있습니까 ? f
아래 방법으로는 위의 문제를 어떻게 해결하는지 모르겠습니다.
#!/bin/bash
f="/tmp/file" # no extension
timestamp="$(date +%H%M%S)"
echo "${f%%.*}-$timestamp.${f#*.:-not found}"
결과:
$ ./test.sh
/tmp/file-221420./tmp/file
답변1
/tmp/dir.d/file
파일 문제 도 발생합니다 .
그리고 zsh
:
#! /bin/zsh -
f="/tmp/file.txt" # with .txt extension
timestamp=${(%):-%D{%H%M%S}}
set -o extendedglob
extension=${(M)f%.[^./]#}
print -r -- ${f%$extension}-$timestamp$extension
표준 sh
구문을 사용하십시오(bash/zsh에서도 작동함):
#! /bin/sh -
f="/tmp/file.txt" # with .txt extension
timestamp=$(date +%H%M%S)
case ${f##*/} in
(*.*) printf '%s\n' "${f%.*}-$timestamp.${f##*.}";;
(*) printf '%s\n' "$f-$timestamp";;
esac
를 사용하면 명령 실행을 피하기 위해 로 bash
바꿀 수 있습니다 .timestamp=$(date +%H%M%S)
printf -v timestamp '%(%H%M%S)T'
date
답변2
간단한 솔루션을 원할 경우 다소 우아하지 않지만 실행 가능한 솔루션의 데모는 다음과 같습니다.
#!/bin/bash
# Test cases
FILE="/tmp/file"
# FILE="/tmp/file."
# FILE="/tmp/file.txt"
# FILE="/tmp/file.txt."
# TIMESTAMP="$(date +%H%M%S)"
printf -v TIMESTAMP '%(%H%M%S)T'
echo "${FILE%%.*}-${TIMESTAMP}.$([[ $FILE =~ \..*$ ]] && { echo "${FILE#*.}"; } || { echo "txt"; })"
.txt
확장자가 없으면 위의 내용이 파일 이름에 추가됩니다.
확장자가 누락된 경우 기본 확장자를 파일 이름에 추가하지 않으려면 다음 코드 줄을 사용하십시오.
echo "${FILE%%.*}-${TIMESTAMP}$([[ $FILE =~ \..*$ ]] && { echo ".${FILE#*.}"; })"
답변3
단순화를 위해
#!/bin/bash
f="/tmp/file"
timestamp="$(date +%H%M%S)"
out="${f}-${timestamp}";
[ "${f%.*}" != "${f##*.}" ] && out="${f%.*}-${timestamp}.${f##*.}";
echo "$out"
.
길을 안전하게 만들어라
dir=${f%/*};
file=${f##*/};
name=${file%.*};
suffix=${file##*.};
[ "$dir" != "$file" ] && dir=${dir}/ || unset dir;
[ "$name" != "$suffix" ] && suffix=.${suffix} || unset suffix;
echo "${dir}${name}-${timestamp}${suffix}"
줄 바꿈을 연속으로 제거해야 하는 경우
다음을 참고하세요. 고유한지 확인하기 위해 전체 타임스탬프(날짜 + 시간)를 사용하는 것이 좋습니다.
답변4
정의 되지 않은 것이 아니라 f
첫 번째 점이 삭제되기 전 해당 부분의 값입니다 ${f#*.}
. f
점이 없으면 ${f#*.}
와 마찬가지로 아무것도 삭제되지 않습니다 $f
. 게다가 일치하기 때문에첫 번째./foo.txt
포인트, 당신은 (it give) 와 같은 경로 문제를 갖게 될 것입니다 -181548./foo.txt
.
점으로 구분된 접미사 없이 비어 있게 되는 ${f#*.}
같음 $f
또는 이와 유사한 것을 테스트해야 합니다 . ${f#${f%.*}}
이에 따라 ${f%.${f##*.}}
여전히 문제가 다시 발생합니다 ./file
.
질문은 ./file
먼저 경로에서 파일 이름 부분을 분할한 다음 거기서부터 계속하는 것을 제안합니다.
또 다른 방법은 정규식을 사용하는 것입니다. 이것은 내가 테스트한 파일 이름에 적용됩니다.
#!/bin/bash
f=$1
timestamp="$(date +%H%M%S)"
re='^((.*/)?[^/.]+)(\.[^/]+)?$'
if [[ $f =~ $re ]]; then
echo "${BASH_REMATCH[1]}-${timestamp}${BASH_REMATCH[3]}"
fi
즉 (.*/)?
, 슬래시로 끝나는 선택적 경로입니다. [^/.]+
- 파일 이름의 초기 부분입니다 (\.[^/]+)?
.