Как узнать, является ли файл в цикле последним?
Пример
for FILE in $DIR/*
do
if(<is last File>)
doSomethingSpecial($FILE)
else
doSomethingRegular($FILE)
fi
done
Как вызвать <is last file>
, чтобы проверить, является ли текущий файл последним в массиве?
Есть ли простая встроенная проверка без проверки длины массива самостоятельно?
Ответы
Ответ 1
Что нужно, чтобы проверить, является ли текущий файл последним в массиве?
Для начала вы не используете массив. Если бы вы были тогда, это было бы легко:
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
Ответ 2
Я знаю, что не могу сказать, что вы обрабатываете последний элемент списка в цикле 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. Пространство необходимо, так как :-
обрабатывается по-разному с : -
.
Ответ 3
Попробуйте это
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
Ответ 4
Что делает файл последним? Есть ли что-то особенное? Это файл с наибольшим именем при сортировке по имени?
Возможно, вы можете взять имена файлов назад. Затем, это первый файл, который вы хотите обработать специальным, а не последним. вычисление первой задачи намного проще, чем выполнение последнего:
for file in $(ls -r1 $dir)
do
if [ ! $processedLast ]
then
doSomethingSpecial($file)
processedLast=1
else
doSomethingRegular($file)
fi
done
Никаких массивов не требуется. На самом деле, мне нравится chepner ответить об использовании позиционных параметров.
Ответ 5
Вы можете использовать find, чтобы найти общее количество файлов.
Затем, когда вы находитесь в цикле, подсчитываете общее число и выполняете свою задачу, когда сумма равна счету i.e, последнему файлу.
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
Ответ 6
Вы можете злоупотреблять позиционными параметрами, поскольку они действуют аналогично массиву,
но их немного легче манипулировать. Вы должны либо сохранить старый позиционный
параметры или выполнить в подоболочке.
# 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=( "[email protected]" )
set -- "${files[@]}"
until (( $# == 1 )); do
doSomethingRegular "$1"
shift
done
doSomethingSpecial "$1"
set -- "${oldPP[@]}"
Ответ 7
Основываясь на текущем наивысшем голосовании от @cdarke (fooobar.com/questions/482501/...), если смотреть на общий массив значений (а не на определенные файлы на диске), код цикла будет выглядеть следующим образом:
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/* )
... это, вероятно, меньше беспокоит, так как отдельные имена файлов в одном каталоге почти наверняка уникальны (если у вас нет действительно нечетной файловой системы!)
Ответ 8
Старый вопрос - но, основываясь на ответе от @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