创build新文件,但如果文件名已存在于bash中,则添加数字

我发现了类似的问题,但不是在Linux / Bash中

我想我的脚本创build一个给定名称的文件(通过用户input),但如果文件名已经存在,最后添加数字。

例:

$ create somefile Created "somefile.ext" $ create somefile Created "somefile-2.ext" 

谢谢阅读

Solutions Collecting From Web of "创build新文件,但如果文件名已存在于bash中,则添加数字"

以下脚本可以帮助你。 您不应该同时运行多个脚本副本,以避免竞争状况。

 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")"