ファイルを繰り返していくつかの操作を実行するスクリプトがあります。文字列の置き換え日付を挿入してください。
#!/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
つまり(.*/)?
、スラッシュで終わるオプションのパスです。[^/.]+
- ファイル名の初期部分です(\.[^/]+)?
。