Ответы:
for file in $(ls -p | grep -v / | tail -100)
do
mv $file /other/location
done
Это предполагает , что имена файлов не содержат пробелы, символы новой строки (предполагается , что значение по умолчанию $IFS
), подстановочные символы ( ?
, *
, [
) или начать с -
.
ls
. И всегда двойные кавычки параметров и командных подстановок.
find
команде не хватало. Аргумент был в неправильном месте, и я добавил нулевые окончания имени файла. Это немного длинная строка, но это все, что я могу сделать в комментарии. Вот исправленный фрагмент:find . -maxdepth 1 -type f \( ! -iname ".*" \) -print0 | while read -rd $'\0' file ; do mv -- "$file" /other/location/ ; done
read -d
опция не переносится на все оболочки, но если вы используете ее в bash
любом случае, -d ''
вы получите тот же эффект, что и -d $'\0'
.
;
где сейчас находится каждая новая строка .
Это проще всего в Zsh:
mv -- *([1,100]) /other/location/
При этом перемещаются первые 100 не скрытых файлов (любого типа, изменяются ([1,100])
только (.[1,100])
на обычные файлы или (^/[1,100])
для любого типа, кроме каталога ) в лексикографическом порядке имен. Вы можете выбрать другой порядок сортировки с помощью o
квалификатора glob , например, чтобы переместить 100 самых старых файлов:
mv -- *(Om[1,100]) /other/location/
С другими оболочками вы можете сделать это в цикле с ранним выходом.
i=0
for x in *; do
if [ "$i" = 100 ]; then break; fi
mv -- "$x" /other/location/
i=$((i+1))
done
Другой переносимый способ - создать список файлов и удалить все, кроме последних 100 .
$(( i++ ))
или $[ i++ ]
?
++
и --
. Вы можете написать : $((i+=1))
вместо i=$((i+1))
; Я не уверен, что это более читабельно.
ls -p | grep -v /
так же, как и недавний вопрос, который возникает здесь.
Если вы не используете zsh:
set -- *
[ "$#" -le 100 ] || shift "$(($# - 100))"
mv -- "$@" /target/dir
Переместил бы последние (в алфавитном порядке) 100 единиц.
Следующий oneliner в оболочке поможет.
foreach i (`find Source_Directory -type f --max-deep 1 | tail -100`); делать; {mv $ i Target_Directory}; сделанный
zsh
даже если на первый взгляд это выглядит совершенно чуждо zsh
синтаксису. Жиль показал гораздо более простой способ сделать это zsh
. Даже тогда, это все еще более надежно, чем принятый в настоящее время ответ.
shuf -n 100 -e * | xargs -i mv {} path-to-new-folder
mmv - выдающаяся утилита, которая также позволит вам делать массовые переименования файлов. (Мне пришлось sudo apt-get install mmv
установить его на своем компьютере.) Простой пример использования: предположим, у вас есть каталог файлов с расширением .JPG, который вы хотите изменить на строчный .jpg. Следующая команда добивается цели:
mmv \*.JPG \#1.jpg
Обратная косая черта используется для обозначения подстановочного знака. * / JPG соответствует чему-либо с расширением JPG. В части «to» команды # 1 использует соответствующий текст из первого подстановочного знака для переименования файла. Конечно, вы можете поставить другой путь перед # 1, чтобы также переместить файл.
Следующая команда работает, если вы заинтересованы в использовании ls
$ ls -rt source/* | head -n100 | xargs cp -t destination
Как это работает ??
ls -rt source/*
- команда выводит список всех файлов с относительным путемhead -n100
- занимает первые 100 файловxargs cp -t destination
- перемещает эти файлы в папку назначенияПопробуй это:
find /source/directory -type f -maxdepth 1 -print | tail -100 | xargs -J % mv % /other/location/
mv
, последний из которых (вероятно) не является каталогом. И это на самом деле не отвечает на вопрос - спрашивающий хочет переместить заданное количество файлов, а не все.
Я пришел сюда, но мне нужно было копировать файлы по частям (по 99) /DIR1
в /DIR2
. Я вставлю сценарий сюда, чтобы помочь другим, может быть:
#!/bin/bash
# Thanks to <Jordan_U> @ #ubuntu
# 06 Dec 2014
i=0
copy_unit=98
for file in /DIR1/*; do
cp "$file" /DIR2
if [[ "$i" -ge "$copy_unit" ]]; then
echo "Pausing, press enter to continue"
read
i=0
fi
((i++))
done
Если вы хотите быть в безопасности / обрабатывать имена файлов с пробелами, символами новой строки, кавычками, обратной косой чертой и т. Д., Вы должны использовать разделители с нулевым символом в конце:
find "$srcdir" -maxdepth 1 -type f -print0 | head -z -n 100 | xargs -0 -r -- mv -t "$destdir" --
EDIT2: Примечание: если у вас нет head -z
( по любой причине ) , вы можете заменить выше head -z -n 1000
с tr '\0\n' '\n\0' | head -n 1000 | tr '\0\n' '\n\0'
(или увидеть другие способы )
-maxdepth 1
не будет искать файлы в подкаталогах $srcdir
, поэтому в списке указаны только файлы $srcdir
.
-print0
будет использовать \0
вместо newline ( \n
) между каждым перечисленным файлом - это помогает обрабатывать файлы, содержащие символы новой строки и пробелы с xargs.
head -z
будет считать \0
завершенные (вместо newline ( \n
) прекращенные) строки как строки. -n 100
будет перечислять только первые найденные 100
файлы find
.
Если вы хотите увидеть, какая команда xargs
будет выполняться, добавьте -t
(или --verbose
).
xargs -0
«Элементы ввода завершаются символом null ( \0
) вместо пробела, а кавычки и обратный слеш не являются специальными (каждый символ воспринимается буквально)»
xargs -r
не будет запускатьсяmv
если нет файлов для перемещения (т. е. если find
не найдено ни одного файла).
--
прекращает обработку аргументов как опций для программы, подробнее здесь
Пример вывода (запускает одну mv
команду и может обрабатывать файлы с символами новой строки в их имени):
$ find /tmp/t -maxdepth 1 -type f -print0 | head -z -n 100 | xargs -t -0 -r -- mv -t /tmp -- ; echo "exit codes: ${PIPESTATUS[@]}"
mv -t /tmp -- /tmp/t/file containing quotes"' then spaces /tmp/t/file containing quotes"' /tmp/t/file containing a slash n here\n /tmp/t/file containing a new line here
and continues /tmp/t/s /tmp/t/-x and -L 1. /tmp/t/of replace-str in the initi /tmp/t/-thisfile_starts_with_a_hyphen and has spaces and a -hyphen here /tmp/t/-thisfile_starts_with_a_hyphen and has spaces /tmp/t/-thisfile_starts_with_a_hyphen /tmp/t/another with spaces /tmp/t/one with spaces /tmp/t/c /tmp/t/a
exit codes: 0 0 0
$ ls -1R /tmp/t
/tmp/t:
a
'another with spaces'
b
c
'file containing a new line here'$'\n''and continues'
'file containing a slash n here\n'
'file containing quotes"'\'''
'file containing quotes"'\'' then spaces'
'of replace-str in the initi'
'one with spaces'
s
'some dir'
-thisfile_starts_with_a_hyphen
'-thisfile_starts_with_a_hyphen and has spaces'
'-thisfile_starts_with_a_hyphen and has spaces and a -hyphen here'
'-x and -L 1.'
/tmp/t/b:
'file with spaces'
'/tmp/t/some dir':
'some file'
Для find
:
-maxdepth levels
Descend at most levels (a non-negative integer) levels of direc‐
tories below the starting-points. -maxdepth 0
means only apply the tests and actions to the starting-points
themselves.
-type c
File is of type c:
b block (buffered) special
c character (unbuffered) special
d directory
p named pipe (FIFO)
f regular file
l symbolic link; this is never true if the -L option or the
-follow option is in effect, unless the symbolic link is
broken. If you want to search for symbolic links when -L
is in effect, use -xtype.
s socket
D door (Solaris)
-P Never follow symbolic links. This is the default behaviour.
When find examines or prints information a file, and the file is
a symbolic link, the information used shall be taken from the
properties of the symbolic link itself.
-L Follow symbolic links. When find examines or prints information
about files, the information used shall be taken from the prop‐
erties of the file to which the link points, not from the link
itself (unless it is a broken symbolic link or find is unable to
examine the file to which the link points). Use of this option
implies -noleaf. If you later use the -P option, -noleaf will
still be in effect. If -L is in effect and find discovers a
symbolic link to a subdirectory during its search, the subdirec‐
tory pointed to by the symbolic link will be searched.
When the -L option is in effect, the -type predicate will always
match against the type of the file that a symbolic link points
to rather than the link itself (unless the symbolic link is bro‐
ken). Actions that can cause symbolic links to become broken
while find is executing (for example -delete) can give rise to
confusing behaviour. Using -L causes the -lname and -ilname
predicates always to return false.
Для head
:
-n, --lines=[-]NUM
print the first NUM lines instead of the first 10; with the
leading '-', print all but the last NUM lines of each file
-z, --zero-terminated
line delimiter is NUL, not newline
РЕДАКТИРОВАТЬ: Кто-то упомянул, что у них не было head -z
, это версия, которую я использовал (в Fedora 25):
$ head --version
head (GNU coreutils) 8.25
Copyright (C) 2016 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Written by David MacKenzie and Jim Meyering.
$ rpm -qf /usr/bin/head
coreutils-8.25-17.fc25.x86_64
Для xargs
:
-0, --null
Input items are terminated by a null character instead of by
whitespace, and the quotes and backslash are not special (every
character is taken literally). Disables the end of file string,
which is treated like any other argument. Useful when input
items might contain white space, quote marks, or backslashes.
The GNU find -print0 option produces input suitable for this
mode.
-r, --no-run-if-empty
If the standard input does not contain any nonblanks, do not run
the command. Normally, the command is run once even if there is
no input. This option is a GNU extension.
-P max-procs, --max-procs=max-procs
Run up to max-procs processes at a time; the default is 1. If
max-procs is 0, xargs will run as many processes as possible at
a time. Use the -n option or the -L option with -P; otherwise
chances are that only one exec will be done. While xargs is
running, you can send its process a SIGUSR1 signal to increase
the number of commands to run simultaneously, or a SIGUSR2 to
decrease the number. You cannot increase it above an implemen‐
tation-defined limit (which is shown with --show-limits). You
cannot decrease it below 1. xargs never terminates its com‐
mands; when asked to decrease, it merely waits for more than one
existing command to terminate before starting another.
Please note that it is up to the called processes to properly
manage parallel access to shared resources. For example, if
more than one of them tries to print to stdout, the ouptut will
be produced in an indeterminate order (and very likely mixed up)
unless the processes collaborate in some way to prevent this.
Using some kind of locking scheme is one way to prevent such
problems. In general, using a locking scheme will help ensure
correct output but reduce performance. If you don't want to
tolerate the performance difference, simply arrange for each
process to produce a separate output file (or otherwise use sep‐
arate resources).
-t, --verbose
Print the command line on the standard error output before exe‐
cuting it.
Для cp
:
-t, --target-directory=DIRECTORY
copy all SOURCE arguments into DIRECTORY
-v, --verbose
explain what is being done
Еще один вариант, вдохновленный https://unix.stackexchange.com/a/105042/66736 :
cp `ls -d ./* | head -n 100` tmpi
Это может быть не самый быстрый или самый элегантный способ, но это способ, который вы можете сохранить в памяти.
Я знаю, что эта ветка довольно старая, но я нашел ответы более сложными, чем я думал, что они должны быть. Это сработало в CentOS, но кажется достаточно простым, чтобы оно могло работать в других дистрибутивах.
cp `ls someDir | head -n 100` someDir100/
ls
не будет содержать somedir/
начальный префикс, и не будет работать для имени файла с пустыми или подстановочными символами или начинаться с -
.
ls | head -n 100
../someDir100/ из целевого каталога, и ни одно из имен файлов не удовлетворяло этим случаям. Лучше быть удачливым, чем хорошим!
about.com
и на какой-то другой веб-сайт, чтобы получить список доступных опций, которые я могу использовать ... но не нашел ничего подобногоtail