我发现了类似的问题,但不是在Linux / Bash中
我想我的脚本创build一个给定名称的文件(通过用户input),但如果文件名已经存在,最后添加数字。
例:
$ create somefile Created "somefile.ext" $ create somefile Created "somefile-2.ext"
谢谢阅读
以下脚本可以帮助你。 您不应该同时运行多个脚本副本,以避免竞争状况。
name=somefile if [[ -e $name.ext ]] ; then i=0 while [[ -e $name-$i.ext ]] ; do let i++ done name=$name-$i fi touch "$name".ext
为了避免竞争条件 :
name=some-file n= set -C until file=$name${n:+-$n}.ext { command exec 3> "$file"; } 2> /dev/null do ((n++)) done printf 'File is "%s"\m' "$file" echo some text in it >&3
此外,你有文件在fd 3上打开。
事实上,这并不能真正消除竞争条件。 set -C
只能防止clobering 常规文件(所以cmd > /dev/null
例如不会失败),并且在大多数shell中都有竞争条件。
如果有这个名字的文件,shell首先对它做一个stat(2)
来检查它是否是一个普通的文件(fifo,directory,device …)。 只有当文件不存在或者是一个普通文件时, 3> "$file"
使用O_EXCL标志来保证不会破坏文件。
所以如果有这个名字的fifo或设备文件,它将被使用(只要它是可写的就可以打开),如果一个普通的文件被替换为fifo / device /目录,它可能会被破坏。 ..之间的stat(2)
和open(2)
没有O_EXCL!
对于一个工作版本,你可以使用zsh
:
zmodload zsh/system name=some-file n= until file=$name${n:+-$n}.ext sysopen -w -o excl -u 3 -- "$file" 2> /dev/null do ((n++)) done printf 'File is "%s"\m' "$file" echo some text in it >&3
尝试像这样(未经测试,但你明白了):
filename=$1 # If file doesn't exist, create it if [[ ! -f $filename ]]; then touch $filename echo "Created \"$filename\"" exit 0 fi # If file already exists, find a similar filename that is not yet taken digit=1 while true; do temp_name=$filename-$digit if [[ ! -f $temp_name ]]; then touch $temp_name echo "Created \"$temp_name\"" exit 0 fi digit=$(($digit + 1)) done
根据你在做什么,用你需要的任何代码来替换touch
来创建你正在使用的文件。
尝试这样的事情
name=somefile path=$(dirname "$name") filename=$(basename "$name") extension="${filename##*.}" filename="${filename%.*}" if [[ -e $path/$filename.$extension ]] ; then i=2 while [[ -e $path/$filename-$i.$extension ]] ; do let i++ done filename=$filename-$i fi target=$path/$filename.$extension
这是一个更好的方法,我用来增量创建目录。
它也可以调整文件名。
LAST_SOLUTION=$(echo $(ls -d SOLUTION_[[:digit:]][[:digit:]][[:digit:]][[:digit:]] 2> /dev/null) | awk '{ print $(NF) }') if [ -n "$LAST_SOLUTION" ] ; then mkdir SOLUTION_$(printf "%04d\n" $(expr ${LAST_SOLUTION: -4} + 1)) else mkdir SOLUTION_0001 fi
简单重新包装choroba的答案作为一个广义函数:
autoincr() { f="$1" ext="" # Extract the file extension (if any), with preceeding '.' [[ "$f" == *.* ]] && ext=".${f##*.}" if [[ -e "$f" ]] ; then i=1 f="${f%.*}"; while [[ -e "${f}_${i}${ext}" ]]; do let i++ done f="${f}_${i}${ext}" fi echo "$f" } touch "$(autoincr "somefile.ext")"