В моей папке у меня есть несколько файлов, похожих на эти:

ContractAdjustments.CHRS201804202144.txt
ContractAdjustments.CHRS201804212144.txt
ContractAdjustments.CHRS201804222144.txt
ContractAdjustments.CHRS201804232144.txt

Я хочу сохранить только самый молодой файл, а остальные переместить в архив. Я использую следующий скрипт, который дает мне ошибку:

$ find -maxdepth 1 -type f -iname 'ContractAdjustments.*.TXT' -printf '%T@|%p\n' | sort -r -n | tail -n +2 | cut -d'|' -f2 | xargs -i mv {} ARCHV
1
Minix 27 Июн 2018 в 04:56
Всегда ли файлы в этом каталоге имеют именно этот формат и являются ли они единственными файлами в этом каталоге?
 – 
Nasir Riley
27 Июн 2018 в 00:13
Что именно для вас означает «последний»?
 – 
Jeff Schaller
27 Июн 2018 в 00:34
Это означает, что каждый день я получаю более 1 файла, мне нужно сохранить только один последний файл, а остальные нужно заархивировать перед его обработкой.
 – 
madhukar korakandla
27 Июн 2018 в 00:38
Я использую этот скрипт, я получаю ошибку
 – 
madhukar korakandla
27 Июн 2018 в 00:46
$ find -maxdepth 1 -type f -iname 'ContractAdjustments.*.TXT' -printf '%T@|%p\n' | сортировать -r -n | хвост -n +2 | вырезать -d'|' -f2 | xargs -i mv {} АРХИВ
 – 
madhukar korakandla
27 Июн 2018 в 00:46

4 ответа

#!/bin/sh

mkdir -p ARCHIVE || exit 1

newest=
for file in ContractAdjustments.*.txt; do
    if [ -f "$file" ]; then
        if [ -z "$newest" ]; then
            # this is the first file, initialize "newest"
            newest=$file
        elif [ "$file" -nt "$newest" ]; then
            # file is newer than "newest",
            # archive "newest" and set new newest file
            mv -i "$newest" ARCHIVE
            newest="$file"
        else
            # file is older, archive it
            mv -i "$file" ARCHIVE
        fi
    fi
done

if [ -n "$newest" ]; then
    printf 'Done. Newest file = %s\n' "$newest"
else
    echo 'No files found'
fi

Этот сценарий, при условии, что /bin/sh реализует тест -nt во встроенной команде [, перемещает все старые файлы в папку ARCHIVE, сохраняя при этом самый новый файл нетронутым. .

Он делает это, перебирая имена файлов, соответствующие заданному шаблону, и для каждого файла проверяя его отметку времени относительно самого нового файла, найденного на данный момент, перемещая файлы в зависимости от того, являются ли они более новыми или старыми.

Сценарий должным образом заботится о сохранении любых пробелов и т. д. в именах файлов. Это может не быть проблемой в данном конкретном случае, но в целом имя файла Unix может содержать как пробелы, так и встроенные символы новой строки, а также символы подстановки имени файла.


Если вы хотите сортировать по имени файла, а не по меткам времени в файлах:

#!/bin/sh

mkdir -p ARCHIVE || exit 1

set -- ContractAdjustments.*.txt

while [ "$#" -gt 1 ]; do
    mv -i "$1" ARCHIVE
    shift
done

printf 'Done. Newest file = %s\n' "$1"

Это установит позиционные параметры ($1, $2 и т. д.) в список файлов, соответствующих заданному шаблону. Затем, пока в списке еще больше одного файла, переместите первый файл в списке в каталог ARCHIVE и удалите его из списка. Последний файл в списке — это тот, который сортируется последним по имени файла (этот файл остается на месте).

1
Kusalananda 27 Июн 2018 в 09:20
Нет. Если вы не имеете в виду, что хотите обернуть его в скрипт или в функцию оболочки? Код уже написан как скрипт.
 – 
Kusalananda
27 Июн 2018 в 16:54
Я написал так, но он удаляет только один старый файл, мне нужно сохранить только один последний, а расширение нужно перенести в архив. #!/bin/bash targetfile="$(ls /opt/informatica/server/infa_shared/MDM/SrcFiles /HealthTrust/ContractAdjustments.*.txt | sort -r | tail -n1)" if [[ -f "$targetfile" ]]; затем mv $targetfile /opt/informatica/server/infa_shared/MDM/SrcFiles/HealthTrust/Archive/fi
 – 
madhukar korakandla
27 Июн 2018 в 16:57
Эта команда не имеет ничего общего с моим ответом.
 – 
Kusalananda
27 Июн 2018 в 17:01

Простой способ сделать это:

mv `ls -t ContractAdjustments.*.txt | awk '{ iteration+=1; if (iteration > 1) { print } } ' ` ARCHV

Конечно, это приведет к ошибкам в пограничных условиях (например, если в каталоге только один файл), но это всегда будет работать.

0
wineguy 27 Июн 2018 в 03:52

Поместите список всех файлов, кроме первого, в переменную и запустите для него цикл for.

 listinmemory=`ls -alht | tail -n +5 | awk '{print $9}'`; for each in $listinmemory; do mv $each /path/to/directory; done

ls -alht перечислит 4 строки, на которых вы не хотите ничего запускать,

total 123K
drwxr-xr-x.  5 user user 1.0K Jun 27 09:20 .
drwx------. 13 user user 2.0K Jun 27 10:36 ..
-rw-rw-r--.  1 user user 3.0K Jun  6 18:29 file1 

Самый последний файл и 3 строки -- затем все файлы, которые вы делаете, поэтому tail -n +5 пропустит первые 4 строки и запустит mv $each /path/to/directory для всех найденных файлов!

0
CubeSyVal 27 Июн 2018 в 07:00

Не рекомендуется анализировать ls, поэтому в вашем случае cd в каталог и выполните следующее:

 for CA in $(find . -maxdepth 1 -type f -name ContractAdjustments\*.txt | head --lines=-1); do mv $CA /path/to/archive/; done

Используя цикл for с подстановкой команд, он находит все файлы в каталоге, начиная с указанного вами формата ContractAdjustments*.txt, и перечисляет их в порядке от самых старых до самых новых в соответствии с датой второй октет. Затем он передается в --head --lines=-1, который печатает все, кроме последней строки, которая является самым новым файлом, и передает значение переменной CA (для ContractAdjustments). Наконец, do использует mv для перемещения всех файлов, кроме самого нового, в расположение архива.

0
Nasir Riley 27 Июн 2018 в 08:04