例子
for FILE in $DIR/*
do
if(<is last File>)
doSomethingSpecial($FILE)
else
doSomethingRegular($FILE)
fi
done
调用什么来<is last file>
检查当前文件是否是数组中的最后一个?
是否有一个简单的内置检查而不自己检查数组的长度?
调用什么来检查当前文件是否是数组中的最后一个?
首先,您没有使用数组。如果你是那么这将很容易:
declare -a files
files=($DIR/*)
pos=$(( ${#files[*]} - 1 ))
last=${files[$pos]}
for FILE in "${files[@]}"
do
if [[ $FILE == $last ]]
then
echo "$FILE is the last"
break
else
echo "$FILE"
fi
done
我不知道您正在处理 for 循环中列表的最后一个元素。但是,您可以使用数组,遍历除最后一个元素之外的所有元素,然后在循环外处理最后一个元素:
files=($DIR/*)
for file in "${files[@]::${#files[@]}-1}" ; do
doSomethingRegular "$file"
done
doSomethingSpecial "${files[@]: -1:1}"
扩展${files[@]:offset:length}
计算元素的所有从开始offset
(或开头,如果为空)的length
元素。${#files[@]}-1
是数组中的元素数减 1。
${files[@]: -1:1}
计算到最后一个元素 - 从末尾开始的 -1,长度为 1。空格是必要的,因为与 .:-
的处理方式不同: -
。
尝试这个
LAST_FILE=""
for f in *
do
if [ ! -z $LAST_FILE ]
then
echo "Process file normally $LAST_FILE"
fi
LAST_FILE=$f
done
if [ ! -z $LAST_FILE ]
then
echo "Process file as last file $LAST_FILE"
fi
生产
bash[1051]: ls
1 2 3 4
bash[1052]: sh ../last_file.sh
Process file normally 1
Process file normally 2
Process file normally 3
Process file as last file 4
您可以使用 find 来查找文件总数。然后当你在循环中计数到总数并在总数等于计数时执行你的任务,即最后一个文件。
f=0
tot_files=`find . -iname '*.txt' | wc -l`
for FILE in $DIR/*
do
f=($f+1)
if [[ $f == $tot_files ]];then
carryout your task
fi
done
基于@cdarke(https://stackoverflow.com/a/12298757/415523)的当前最高投票答案,如果查看一般的值数组(而不是磁盘上的特定文件),循环代码将是如下:
declare -a array
declare -i length current
array=( a b c d e c )
length=${#array[@]}
current=0
for VALUE in "${array[@]}"; do
current=$((current + 1))
if [[ "$current" -eq "$length" ]]; then
echo "$VALUE is the last"
else
echo "$VALUE"
fi
done
这会产生输出:
a
b
c
d
e
c is the last
这确保只有数组中的最后一项触发替代操作,并且如果数组中的任何其他项与最后一个值重复,则不会为较早的重复项调用替代操作。
在特定目录中文件的路径数组的情况下,例如
array=( $DIR/* )
...这可能不是一个问题,因为同一目录中的各个文件名几乎肯定是唯一的(除非您有一个非常奇怪的文件系统!)
是什么让文件成为最后一个?它有什么特别之处吗?按名称排序时,它是名称最大的文件吗?
也许你可以把文件名倒过来。然后,它是您要特殊处理的第一个文件,而不是最后一个。找出第一个比做最后一个要容易得多:
for file in $(ls -r1 $dir)
do
if [ ! $processedLast ]
then
doSomethingSpecial($file)
processedLast=1
else
doSomethingRegular($file)
fi
done
不需要数组。实际上,我喜欢chepner关于使用位置参数的回答。
您可以滥用位置参数,因为它们的作用类似于数组,但更容易操作。您应该保存旧的位置参数,或者在子shell 中执行。
# Method 1: use a subshell. Slightly cleaner, but you can't always
# do this (for example, you may need to affect variables in the current
# shell
files=( $DIR/* )
(
set -- "${files[@]}"
until (( $# == 1 )); do
doSomethingRegular "$1"
shift
done
doSomethingSpecial "$1"
)
# Method 2: save the positional parameters. A bit uglier, but
# executes everything in the same shell.
files=( $DIR/* )
oldPP=( "$@" )
set -- "${files[@]}"
until (( $# == 1 )); do
doSomethingRegular "$1"
shift
done
doSomethingSpecial "$1"
set -- "${oldPP[@]}"
这是个老问题 - 但基于@GregReynolds 的回答,如果命令仅在最后一次传递的参数上有所不同,请使用此单行代码。单行爱好者的丑陋,丑陋的代码
( ff="" ; for f in * "" ; do [ -n "$ff" ] && echo $(${f:+false} && echo $ff alternate params here || echo normal params $ff ) ; ff=$f ; done )
normal params 1
normal params 2
normal params 3
4 alternate params here