Вопрос копировать n количество файлов из одной папки в другую папку


У меня есть папка из n числа файлов. Мне нужно переместить n / 2 (или) n / 3 файлов из этой папки в любую другую папку. Как установить значение n так, чтобы оно точно переместило количество файлов?


1
2017-11-19 17:14


происхождения


Не могли бы вы привести пример того, что вы пробовали? - Wilf
@KasiyA Я не согласен, копирование фиксированного числа отличается от копирования относительного числа. Хотя ответ Тердона подходит к этому вопросу. - muru
@KasiyA Нет, как показывает мой ответ. Используя sed для разделения ввода на половину, третью и т. Д., Я мог бы сделать это, не зная, сколько файлов изначально присутствует. - muru


ответы:


Вы могли бы сделать что-то вроде

k=1; find source/ -type f | while read file; do
     [[ k++ -le 20 ]] && cp "$file" target/ 
done

Это найдет все файлы в текущем каталоге и скопирует первые 20, которые он находит target/, Трюк - это $k переменная, которая инициализируется 1, Затем [[ k++ -le 20 ]] && cp означает «Если $ k плюс один меньше или равно 20, запустите команду cp».

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

k=1; find source/ -type f -print0 | 
    while IFS= read -d '' -r file; do 
        [[ k++ -le 20 ]] && cp "$file" target/ 
    done

Если вам не нужно спускаться в подкаталоги, просто выполните

k=1; for file in *; do [[ k++ -le 20 ]] && cp "$file" target/ ; done

Наконец, чтобы вычислить n на лету, вы можете сделать (обратите внимание, что это также будет учитывать подкаталоги)

files=( * ); ## save all files in the current directory in an array
n=$(echo "${#files[@]} / 3 " | bc) ## get the value of n/3
for file in "${files[@]:1:$n}"; do cp "$file" bar/; done

Решение выше должно работать с произвольными именами файлов, включая те, которые включают в себя новые строки.


3
2017-11-19 17:40



Спасибо, что помогли мне улучшить! :-) Вы понимаете, конечно, что последнее решение будет подметать подкаталоги вместе с обычными файлами и пропустить точку (.). ... ... ... Почему вы используете bc когда вам нужен результат, усеченный до целого? (I.e., почему не просто использовать $(( ${#files[@]} / 3 ))?) - G-Man
@ G-Man да, пропуская dotfiles было намеренно, они обычно хотят пропустить (хотя 1-е решение также скопирует их). Что касается подкаталогов, то да, я думал, что добавил к этому отказ, но я написал это перед выходом и спешил. Спасибо, что указали это. я использовал bc по привычке сказать вам правду. Нет веской причины для этого :) - terdon♦


Используйте комбинацию find, sed а также xargs:

find /path/to/dir -print0 | sed -nz '1~2p' | xargs -0 cp --target-dir=/some/dir

sed -n '1~2p' печатает каждую альтернативную линию, тем самым уменьшая счет до половины. Чтобы сделать его третьим, используйте 1~3p, -print0, -z а также -0 варианты указывают, что мы используем \0 (NULL), чтобы разграничить вещи.

Рекомендации:


2
2017-11-19 17:55





Чтобы сделать фракцию (например, & frac13), не зная счет заранее,

к = 0; для файла в *
делать
    если [$ ((k ++% 3)) -eq 0]
    тогда
        mv "$ file" target /
    фи
сделанный

Это будет захватывать каждый третий файл, удерживая счетчик (k) и действует на каждый файл, для которого k кратно 3. Поскольку я начал счетчик в 0, это будет округлено; например, если у вас есть десять или одиннадцать файлов (или двенадцать), он переместит четыре из них.

Если в текущем каталоге есть подкаталоги (или экзотические файлы, такие как FIFO) и вы хотите переместить ⅓ простые файлы, оставив остальных в одиночку, измените

к = 0; для файла в *
делать
    если [-f "$ file"] &&  [$ ((k ++% 3)) -eq 0]
    тогда
        mv "$ file" target /
    фи
сделанный

Если вы хотите спуститься в подкаталоги, скажите

shopt -s globstar

и использовать ** вместо *, Если вы хотите включить имена, начинающиеся с точки (.), вы также должны shopt -s dotglob,

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


2
2017-11-19 21:38