Это простой и прямой способ получить желаемое. Проблема здесь в том, что сканируется весь big_file.txt
. Если это слишком медленно, можно попробовать и другие способы. Одним из них может быть загрузка файла в базу данных с ключом по номерам строк, что даст очень быстрый поиск по сравнению со сканированием файла.
#!/bin/sh
awk '
NR == FNR {
for (i=1; i<=NF; i++) {
linenums[$i]
}
}
NR != FNR {
if (FNR in linenums) {
print
}
}
' line_numbers.txt large_file.txt
NR
- это номер текущей записи (количество записей), а FNR
- номер текущей записи в текущем файле.
Таким образом, когда NR == NFR
awk обрабатывает первый файл arg, когда NR != NFR
awk
обрабатывает второй (или более поздний) файл.
Это считывает все номера строк из line_numbers.txt
и сохраняет их как ключи в массив, в котором нет элементов данных, только ключи (массив linenums
).
При чтении второго файла, big_file.txt
, если номер текущей записи был сохранен как ключ в массиве linenums
, то будет напечатана строка из big_file.txt
.
Метод поиска номеров строк в массиве linenums
относительно быстрый, поскольку awk
использует внутренний алгоритм хэширования для поиска ключей.
Чтобы перемещать заданное количество файлов за раз и спать 5 секунд между перемещениями, вы можете использовать что-то похожее на следующий -лайнер, находясь в исходном каталоге:
while true; do mv -v $(ls -1 *yyy | head -n 5) otherdir/ ; sleep 5; done
Где yyy
соответствует вашему общему расширению файла, -n 5
представляет перемещение 5 файлов за раз, а otherdir
— ваш целевой каталог. Вам нужно будет настроить цикл в соответствии с вашими требованиями, как указано здесь, он выдаст ошибки после перемещения всех исходных файлов.
Небольшой скрипт, который можно настроить так, чтобы он принимал расширение и целевой каталог, выполнит эту задачу:
#!/bin/bash
files=$(find. -maxdepth 1 -type f -name "*.txt" | head -n50)
while [[ ! -z $files ]]; do
for f in $files; do
mv $f../t2
done
files=$(find. -maxdepth 1 -type f -name "*.txt" | head -n50)
done
Протестировано для каталога, в котором я создал 1067 файлов, а затем переместил их.
Я уверен, что есть способ оптимизировать и этот сценарий.
Редактировать:
Как отмечено в комментарии, приведенный выше скрипт не учитывает пробелы. Подход, учитывающий пробелы (, но, возможно, не каждый специальный символ, особенно, возможно, возврат каретки в именах файлов ), может выглядеть так:
#!/bin/bash
function move50() {
local NUM=0
find. -name "*.txt" | head -n50 | (while read -r f; do
echo " $f"
mv "$f"../t2
(( NUM++ ))
done
return $NUM)
}
cntr=1
while [[ $cntr -gt 0 ]]; do
move50
cntr=$?
done
Этот подход будет обрабатывать файлы с пробелами в именах.