Como o Unix e o Linux não têm um grande site sobre suas ferramentas, então simplesmente vou ao site like about.come a algum outro site para obter a lista de opções disponíveis que posso usar .. mas não encontrei nada parecidotail
gaijin
Respostas:
37
for file in $(ls -p | grep -v / | tail -100)
do
mv $file /other/location
done
Que assume nomes de arquivos não contêm espaços em branco, nova linha (assumindo que o valor padrão de $IFS), caracteres curinga ( ?, *, [) ou começar com -.
Observe que essa abordagem só funciona se não houver caracteres especiais (espaço em branco, caracteres não imprimíveis, ``) nos nomes dos arquivos. Como regra geral, não analise a saída dels . E sempre aspas duplas e substituições de comandos.
Gilles 'SO- stop be evil'
1
Qual parte representa 100 arquivos?
Tshepang
3
Atualização para o meu comentário anterior: Depois de ler o link de referência do Gilles, não analise a saída de ls , descobri que meu findcomando estava ausente. Um argumento estava no lugar errado e eu adicionei finais nulos de nome de arquivo. É um pouco longo de uma única linha, mas é tudo o que posso fazer em um comentário. Aqui está o trecho fixo:find . -maxdepth 1 -type f \( ! -iname ".*" \) -print0 | while read -rd $'\0' file ; do mv -- "$file" /other/location/ ; done
Peter.O 11/11
@perer Apenas como uma nota de que a read -dopção não é portável para todos os shells, mas se você estiver usando de bashqualquer maneira, -d ''deve obter o mesmo efeito que -d $'\0'.
Jk013
FWIW, se você deseja que ele seja executado como um oneliner, adicione um ;onde cada nova linha está agora.
patrick
37
É mais fácil no zsh:
mv -- *([1,100]) /other/location/
Isso move os primeiros 100 arquivos não ocultos (de qualquer tipo, a mudança ([1,100])para (.[1,100])a regulares arquivos apenas, ou (^/[1,100])para qualquer tipo mas diretório ) em nome de ordem lexicográfica. Você pode selecionar uma ordem de classificação diferente com o oqualificador glob , por exemplo, para mover os 100 arquivos mais antigos:
mv -- *(Om[1,100]) /other/location/
Com outras conchas, você pode fazer isso em um loop com uma saída antecipada.
i=0
for x in *; do
if [ "$i" = 100 ]; then break; fi
mv -- "$x" /other/location/
i=$((i+1))
done
@phk, isso funcionaria zshmesmo que, à primeira vista, parecesse bastante estranho à zshsintaxe. Gilles mostrou uma maneira muito mais simples de fazer isso zsh. Mesmo assim, isso ainda é mais confiável do que a resposta atualmente aceita.
Stéphane Chazelas
3
O seguinte funcionou para mim. Desculpe se foi publicado anteriormente, mas não o vi em uma verificação rápida.
ls path/to/dir/containing/files/* | head -100 | xargs -I{} cp {} /Path/to/new/dir
O mmv é um excelente utilitário que também permitirá que você renomeie em massa os arquivos. (Eu precisava sudo apt-get install mmvinstalá-lo no meu computador.) Exemplo simples de uso: suponha que você tenha um diretório de arquivos com extensão .JPG que gostaria de mudar para .jpg em minúsculas. O seguinte comando faz o truque:
mmv \*.JPG \#1.jpg
A barra invertida é usada para mostrar que um curinga está chegando. O * / JPG corresponde a qualquer coisa com uma extensão JPG. Na parte "para" do comando, o nº 1 usa o texto correspondente do primeiro curinga para renomear o arquivo. Obviamente, você pode colocar um caminho diferente antes do nº 1 para também mover o arquivo.
Seria mais benéfico se você fornecesse como realmente usaria a ferramenta que sugere para atingir o objetivo.
Dason
1
adicionou um exemplo de uso
Pete
1
#!/bin/bash
c=1; d=1; mkdir -p NEWDIR_${d}
for jpg_file in *.jpg
do
if [ $c -eq 100 ]
then
d=$(( d + 1 )); c=0; mkdir -p NEWDIR_${d}
fi
mv "$jpg_file" NEWDIR_${d}/
c=$(( c + 1 ))
done
Isso está incorreto, você está passando três argumentos mv, o último dos quais (provavelmente) não é um diretório. E isso realmente não responde à pergunta - o solicitante deseja mover um determinado número de arquivos, nem todos.
Mat
Comando atualizado.
Saumil 5/01/12
0
Eu vim aqui, mas estava precisando copiar arquivos em partes (99 cada) de /DIR1para /DIR2. Vou colar o script aqui para ajudar o otherz, talvez:
#!/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
Se você deseja proteger / manipular nomes de arquivos com espaços, novas linhas, aspas, barras invertidas etc., deve usar separadores com terminação nula:
EDIT2: NOTA: se você não tiver head -z( por qualquer motivo ), poderá substituir o acima head -z -n 1000por tr '\0\n' '\n\0' | head -n 1000 | tr '\0\n' '\n\0'(ou ver outras formas )
-maxdepth 1evitará procurar arquivos em subdiretórios de $srcdir, portanto, os únicos listados serão os arquivos contidos $srcdir. -print0usará em \0vez de newline ( \n) entre cada arquivo listado - isso ajuda a lidar com arquivos que contêm novas linhas e espaços com xargs. head -zcontará linhas \0terminadas (em vez de novas \nlinhas terminadas) como linhas. -n 100listará apenas os primeiros 100arquivos findencontrados.
Se você quiser ver qual comando xargsserá executado, adicione -t(ou --verbose). xargs -0"Os itens de entrada são finalizados por um \0caractere nulo ( ) em vez de espaço em branco, e as aspas e a barra invertida não são especiais (todos os caracteres são literalmente)" xargs -rnão será executadomvse não houver arquivos a serem movidos (ou seja, se findnão houver nenhum arquivo). --finaliza o processamento de argumentos como opções para o programa, mais detalhes aqui
Saída de amostra (executa um mvcomando e também pode manipular arquivos com novas linhas em seus nomes):
$ 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'
Para 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.
Para 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
EDIT: Alguém mencionou que não tinha head -z, esta é a versão que eu estava usando (no 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
Para 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.
Para cp:
-t, --target-directory=DIRECTORY
copy all SOURCE arguments into DIRECTORY
-v, --verbose
explain what is being done
Eu sei que esse tópico é muito antigo, mas achei as respostas mais complicadas do que pensei que deveriam ser. Isso funcionou no CentOS, mas parece simples o suficiente para provavelmente funcionar em outras distros.
Isso não funciona porque a saída de lsnão incluirá o somedir/prefixo inicial e não funcionará para o nome do arquivo com caracteres em branco ou curinga ou para começar -.
Stéphane Chazelas
Justo. Na verdade, eu fiz cp ls | head -n 100../someDir100/ De dentro do diretório de destino e nenhum nome de arquivo satisfez esses casos. Melhor ter sorte do que ser bom!
about.com
e a algum outro site para obter a lista de opções disponíveis que posso usar .. mas não encontrei nada parecidotail
Respostas:
Que assume nomes de arquivos não contêm espaços em branco, nova linha (assumindo que o valor padrão de
$IFS
), caracteres curinga (?
,*
,[
) ou começar com-
.fonte
ls
. E sempre aspas duplas e substituições de comandos.find
comando estava ausente. Um argumento estava no lugar errado e eu adicionei finais nulos de nome de arquivo. É um pouco longo de uma única linha, mas é tudo o que posso fazer em um comentário. Aqui está o trecho fixo:find . -maxdepth 1 -type f \( ! -iname ".*" \) -print0 | while read -rd $'\0' file ; do mv -- "$file" /other/location/ ; done
read -d
opção não é portável para todos os shells, mas se você estiver usando debash
qualquer maneira,-d ''
deve obter o mesmo efeito que-d $'\0'
.;
onde cada nova linha está agora.É mais fácil no zsh:
Isso move os primeiros 100 arquivos não ocultos (de qualquer tipo, a mudança
([1,100])
para(.[1,100])
a regulares arquivos apenas, ou(^/[1,100])
para qualquer tipo mas diretório ) em nome de ordem lexicográfica. Você pode selecionar uma ordem de classificação diferente com oo
qualificador glob , por exemplo, para mover os 100 arquivos mais antigos:Com outras conchas, você pode fazer isso em um loop com uma saída antecipada.
Outra maneira portátil seria criar a lista de arquivos e remover todos, exceto os últimos 100 .
fonte
$(( i++ ))
ou$[ i++ ]
?++
e--
. Você pode escrever em: $((i+=1))
vez dei=$((i+1))
; Não estou convencido de que seja mais legível.ls -p | grep -v /
também tem a pergunta recente que engana aqui.Se você não estiver usando o zsh:
Moveria os últimos (em ordem alfabética) 100 unidades.
fonte
O seguinte oneliner no shell ajudaria.
fonte
zsh
mesmo que, à primeira vista, parecesse bastante estranho àzsh
sintaxe. Gilles mostrou uma maneira muito mais simples de fazer issozsh
. Mesmo assim, isso ainda é mais confiável do que a resposta atualmente aceita.O seguinte funcionou para mim. Desculpe se foi publicado anteriormente, mas não o vi em uma verificação rápida.
fonte
De https://stackoverflow.com/questions/14033129/how-to-move-a-given-number-of-random-files-on-unix-linux-os
fonte
O mmv é um excelente utilitário que também permitirá que você renomeie em massa os arquivos. (Eu precisava
sudo apt-get install mmv
instalá-lo no meu computador.) Exemplo simples de uso: suponha que você tenha um diretório de arquivos com extensão .JPG que gostaria de mudar para .jpg em minúsculas. O seguinte comando faz o truque:A barra invertida é usada para mostrar que um curinga está chegando. O * / JPG corresponde a qualquer coisa com uma extensão JPG. Na parte "para" do comando, o nº 1 usa o texto correspondente do primeiro curinga para renomear o arquivo. Obviamente, você pode colocar um caminho diferente antes do nº 1 para também mover o arquivo.
fonte
tente este código
fonte
Tente o seguinte:
fonte
mv
, o último dos quais (provavelmente) não é um diretório. E isso realmente não responde à pergunta - o solicitante deseja mover um determinado número de arquivos, nem todos.Eu vim aqui, mas estava precisando copiar arquivos em partes (99 cada) de
/DIR1
para/DIR2
. Vou colar o script aqui para ajudar o otherz, talvez:fonte
o seguinte comando funciona, se você estiver interessado em usar
ls
Como é que isso funciona ??
ls -rt source/*
- comando lista todos os arquivos com o caminho relativohead -n100
- pega os 100 primeiros arquivosxargs cp -t destination
- move esses arquivos para a pasta de destinofonte
Se você deseja proteger / manipular nomes de arquivos com espaços, novas linhas, aspas, barras invertidas etc., deve usar separadores com terminação nula:
EDIT2: NOTA: se você não tiver
head -z
( por qualquer motivo ), poderá substituir o acimahead -z -n 1000
portr '\0\n' '\n\0' | head -n 1000 | tr '\0\n' '\n\0'
(ou ver outras formas )-maxdepth 1
evitará procurar arquivos em subdiretórios de$srcdir
, portanto, os únicos listados serão os arquivos contidos$srcdir
.-print0
usará em\0
vez de newline (\n
) entre cada arquivo listado - isso ajuda a lidar com arquivos que contêm novas linhas e espaços com xargs.head -z
contará linhas\0
terminadas (em vez de novas\n
linhas terminadas) como linhas.-n 100
listará apenas os primeiros100
arquivosfind
encontrados.Se você quiser ver qual comando
xargs
será executado, adicione-t
(ou--verbose
).xargs -0
"Os itens de entrada são finalizados por um\0
caractere nulo ( ) em vez de espaço em branco, e as aspas e a barra invertida não são especiais (todos os caracteres são literalmente)"xargs -r
não será executadomv
se não houver arquivos a serem movidos (ou seja, sefind
não houver nenhum arquivo).--
finaliza o processamento de argumentos como opções para o programa, mais detalhes aquiSaída de amostra (executa um
mv
comando e também pode manipular arquivos com novas linhas em seus nomes):Para
find
:Para
head
:EDIT: Alguém mencionou que não tinha
head -z
, esta é a versão que eu estava usando (no Fedora 25):Para
xargs
:Para
cp
:fonte
Eu sei que esse tópico é muito antigo, mas achei as respostas mais complicadas do que pensei que deveriam ser. Isso funcionou no CentOS, mas parece simples o suficiente para provavelmente funcionar em outras distros.
fonte
ls
não incluirá osomedir/
prefixo inicial e não funcionará para o nome do arquivo com caracteres em branco ou curinga ou para começar-
.ls | head -n 100
../someDir100/ De dentro do diretório de destino e nenhum nome de arquivo satisfez esses casos. Melhor ter sorte do que ser bom!