21

例子

for FILE in $DIR/* 
do
  if(<is last File>)
    doSomethingSpecial($FILE)
  else
    doSomethingRegular($FILE)
  fi
done

调用什么来<is last file>检查当前文件是否是数组中的最后一个?

是否有一个简单的内置检查而不自己检查数组的长度?

4

8 回答 8

20

调用什么来检查当前文件是否是数组中的最后一个?

首先,您没有使用数组。如果你是那么这将很容易:

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 
于 2012-09-06T11:09:19.180 回答
10

我不知道您正在处理 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。空格是必要的,因为与 .:-的处理方式不同: -

于 2012-09-06T11:00:25.277 回答
5

尝试这个

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
于 2012-09-06T11:04:36.627 回答
3

您可以使用 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
于 2013-09-04T13:40:22.120 回答
3

基于@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/* )

...这可能不是一个问题,因为同一目录中的各个文件名几乎肯定是唯一的(除非您有一个非常奇怪的文件系统!)

于 2015-09-04T20:03:47.217 回答
2

是什么让文件成为最后一个?它有什么特别之处吗?按名称排序时,它是名称最大的文件吗?

也许你可以把文件名倒过来。然后,它是您要特殊处理的第一个文件,而不是最后一个。找出第一个比做最后一个要容易得多:

for file in $(ls -r1 $dir)
do
    if [ ! $processedLast ] 
    then
        doSomethingSpecial($file)
        processedLast=1
    else
        doSomethingRegular($file)
    fi
done

不需要数组。实际上,我喜欢chepner关于使用位置参数的回答。

于 2013-07-22T17:30:23.017 回答
2

您可以滥用位置参数,因为它们的作用类似于数组,但更容易操作。您应该保存旧的位置参数,或者在子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[@]}"
于 2012-09-06T12:17:12.770 回答
1

这是个老问题 - 但基于@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

于 2016-08-22T18:07:23.490 回答