2

У меня есть процесс, который постепенно создает каталоги, присваивает им индекс в порядке возрастания и сохраняет результаты в каталоге последней итерации, который имеет самый большой индекс. Учитывая, что число итераций, необходимых для завершения процесса, варьируется в зависимости от набора данных, я не могу предсказать индекс последнего каталога. Например:

#Dataset 1 may produce
ls -d Dir*
...    Dir4    Dir5

а также

#Dataset 2 may produce
ls -d Dir*
...    Dir34    Dir35

Я догадался, что смогу создать и массив, содержащий имя всех каталогов, сделать копию последнего и удалить все каталоги

ARR=($(ls -d Dir*))
cp ${ARR[@]:(-1)} LastDirectory #Preserve my results in LastDirectory
rm Dir*

Но это верный способ выстрелить себе в ногу. Допустим, программе требуется десять итераций для завершения. Тогда Dir10 будет содержать мои результаты. Если я перечислю каталоги и передам их массиву, Dir10 не будет в последней позиции и будет удален. Это непредсказуемое поведение, которого я хочу избежать!

#You can copy-paste this piece of code to replicate the problem:
mkdir Dir1 Dir2 Dir3 Dir4 Dir5 Dir6 Dir7 Dir8 Dir9 Dir10 
ls -d Dir*
Dir1 Dir10 Dir2 Dir3 Dir4 ... Dir8 Dir9
ARR=($(ls -d Dir*))
echo ${ARR[@]:(-1)}
Dir9

Есть ли безопасный способ избавиться от всех каталогов, кроме каталога с наибольшим индексом?

ПРИМЕЧАНИЕ. Я думал об использовании дат создания каталогов, но, похоже, эта опция не поддерживается в Linux.

5 ответов5

4

На моей Ubuntu есть опция -v для ls . От man ls:

-v натуральный вид (версии) чисел в тексте

В качестве альтернативы опция -V для sort также предназначена для работы с номерами версий. Я решил включить его в свой ответ, потому что sort работает как фильтр. Это может быть удобно в общем случае (например, когда вы получаете список каталогов из find или из текстового файла).

Напишите определение вашего массива следующим образом:

ARR=($(ls -d -v Dir*))

или это:

ARR=($(ls -d Dir* | sort -V))

РЕДАКТИРОВАТЬ: комментарий dave_thompson_085 дает полезное упрощение:

добавление -r к любому из них ставит нужный элемент первым, доступным с более удобным ${ARR[1]} .

0

У sort есть опции -n -r и -k ? Если это так, используйте:

ARR=($( ls -d Dir* | sort -rn -k1.4 ))

Чтобы проверить результат, используйте:

mkdir Dir1 Dir2 Dir3 Dir4 Dir5 Dir6 Dir7 Dir8 Dir9 Dir10 Dir20 Dir100
ARR=($( ls -d Dir* | sort -rn -k1.4 ))
echo ${ARR[@]}

Результат должен быть:

Dir100 Dir20 Dir10 Dir9 Dir8 Dir7 Dir6 Dir5 Dir4 Dir3 Dir2 Dir1

Чтобы сохранить каталог с наибольшим индексом и удалить остальные из них (при условии, что LastDirectory не существует), используйте:

mv ${ARR[0]} LastDirectory # or simply mv $ARR LastDirectory
rm -r Dir* # error if only one Dir* directory, but LastDirectory is preserved

Команда sort -nr -k1.4 использует опцию -k для сортировки имен каталогов с использованием четвертого символа до последнего символа, игнорируя первые три символа. Опция -n сортирует численно, а опция -r меняет порядок так, чтобы наибольшее число было первым.

Замечание о надежности, то есть о том, как справиться с непредвиденными условиями. Решение предполагает, что все имена соответствуют шаблону, где есть три символа « Dir », за которыми следует число, и что LastDirectory не существует. В общем, команда ls хлопотна, потому что она перечисляет имена так, чтобы их было легко читать; но, например, если имя файла имеет встроенный пробел (пустой символ), это имя может нарушить это решение непредсказуемым образом.

0

Можете ли вы (вручную) создать каталог с именем Dir1000 перед началом процесса, а затем он создаст Dir1001 , Dir1002 и т.д.?
Если процесс работает таким образом, это будет очевидно и легко?

0

Поскольку вы не можете изменить программу, которая создает каталоги, как вы упоминали, можете ли вы заставить ее записывать в разные выходные каталоги для каждой задачи? Так что вы бы

Task1
+ Dir1
+ Dir2
Task2
+ Dir3
+ Dir4

В противном случае, возможно, безопаснее посмотреть содержимое каталогов. Есть ли различия между промежуточными каталогами и последним, который содержит результаты? Если результаты находятся только в последнем каталоге, вы можете использовать эту информацию, чтобы выяснить, для чего нужно скопировать результаты и удалить другие каталоги.

0

Если вы согласны с сортировкой каталогов по дате (кажется, что каталог с самым высоким индексом является также самым последним созданным), вы можете сделать это:

ls -1td Dir* | tail -n +2

в котором перечислены все, кроме самого последнего каталога. Чтобы удалить их:

rm $(ls -1td Dir* | tail -n +2)

Ключевым аргументом здесь является -t который сортирует по дате.

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .