Risposte:
for file in $(ls -p | grep -v / | tail -100)
do
mv $file /other/location
done
Che assume i nomi dei file non contengono spazi vuoti, di nuova riga (assumendo il valore di default $IFS
), i caratteri jolly ( ?
, *
, [
) oppure iniziano con -
.
ls
. E sempre virgolette doppie e sostituzioni di comandi.
find
comando mancava. Un arg era nel posto sbagliato e ho aggiunto terminazioni di nomi di file null. È un po 'lungo di una riga, ma è tutto ciò che posso fare in un commento. Ecco lo snippet fisso:find . -maxdepth 1 -type f \( ! -iname ".*" \) -print0 | while read -rd $'\0' file ; do mv -- "$file" /other/location/ ; done
read -d
opzione non è portabile su tutte le shell, ma se stai usando bash
comunque, -d ''
dovresti ottenere lo stesso effetto di -d $'\0'
.
;
cui ogni nuova riga è ora.
È più semplice in zsh:
mv -- *([1,100]) /other/location/
Ciò sposta i primi 100 file non nascosti (di qualsiasi tipo, cambiati ([1,100])
in solo (.[1,100])
per file normali o (^/[1,100])
per qualsiasi tipo tranne directory ) nell'ordine lessicografico dei nomi. È possibile selezionare un diverso ordinamento con il o
qualificatore glob , ad esempio per spostare i 100 file più vecchi:
mv -- *(Om[1,100]) /other/location/
Con altre shell, puoi farlo in un ciclo con un'uscita anticipata.
i=0
for x in *; do
if [ "$i" = 100 ]; then break; fi
mv -- "$x" /other/location/
i=$((i+1))
done
Un altro modo portatile sarebbe quello di costruire l'elenco dei file e rimuovere tutti tranne gli ultimi 100 .
$(( i++ ))
o $[ i++ ]
?
++
e --
. Puoi scrivere : $((i+=1))
invece di i=$((i+1))
; Non sono convinto che sia più leggibile.
ls -p | grep -v /
ha anche la recente domanda che duplica qui.
Se non stai usando zsh:
set -- *
[ "$#" -le 100 ] || shift "$(($# - 100))"
mv -- "$@" /target/dir
Sposta gli ultimi (in ordine alfabetico) di 100.
Il seguente oneliner in shell sarebbe di aiuto.
foreach i (`find Source_Directory -type f --max-depth 1 | tail -100`); fare; {mv $ i Target_Directory}; fatto
zsh
anche se a prima vista sembra abbastanza estraneo alla zsh
sintassi. Gilles ha mostrato un modo molto più semplice di farlo zsh
. Anche allora, è ancora più affidabile della risposta attualmente accettata.
shuf -n 100 -e * | xargs -i mv {} path-to-new-folder
mmv è un'utilità eccezionale che ti permetterà anche di rinominare in massa i file. (Ho dovuto sudo apt-get install mmv
installarlo sul mio computer.) Esempio di semplice utilizzo: supponiamo di avere una directory di file con estensione .JPG che vorresti cambiare in un minuscolo .jpg. Il seguente comando fa il trucco:
mmv \*.JPG \#1.jpg
La barra rovesciata viene utilizzata per mostrare che sta arrivando un carattere jolly. * / JPG corrisponde a qualsiasi cosa con un'estensione JPG. Nella parte "a" del comando, il numero 1 utilizza il testo corrispondente dal primo carattere jolly per rinominare il file. Ovviamente, puoi inserire un percorso diverso prima del n. 1 per spostare anche il file.
il seguente comando funziona, se sei interessato ad usare ls
$ ls -rt source/* | head -n100 | xargs cp -t destination
Come funziona ??
ls -rt source/*
- Il comando elenca tutti i file con il relativo percorsohead -n100
- prende i primi 100 filexargs cp -t destination
- sposta questi file nella cartella di destinazioneProva questo:
find /source/directory -type f -maxdepth 1 -print | tail -100 | xargs -J % mv % /other/location/
mv
, l'ultimo dei quali (probabilmente) non è una directory. E non risponde davvero alla domanda: chi lo desidera desidera spostare un determinato numero di file, non tutti.
Sono venuto qui, ma avevo bisogno di copiare i file in parti (99 ciascuno) da /DIR1
a /DIR2
. Incollerò qui lo script per aiutare gli altri forse:
#!/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 vuoi essere sicuro / gestire nomi di file con spazi, newline, virgolette, barre rovesciate ecc., Devi usare separatori con terminazione null:
find "$srcdir" -maxdepth 1 -type f -print0 | head -z -n 100 | xargs -0 -r -- mv -t "$destdir" --
EDIT2: NOTA: se non hai head -z
( per qualsiasi motivo ) puoi sostituire quanto sopra head -z -n 1000
con tr '\0\n' '\n\0' | head -n 1000 | tr '\0\n' '\n\0'
(o vedere altri modi )
-maxdepth 1
eviterà di cercare file nelle sottodirectory di $srcdir
, quindi gli unici elencati sono i file all'interno $srcdir
.
-print0
utilizzerà al \0
posto di newline ( \n
) tra ogni file elencato - questo aiuta a gestire i file contenenti newline e spazi con xargs.
head -z
conterà le linee \0
terminate (anziché newline ( \n
) terminate) come linee. -n 100
elencherà solo i primi 100
file find
trovati.
Se vuoi vedere quale comando xargs
verrà eseguito, aggiungi -t
(o --verbose
).
xargs -0
"Gli elementi di input sono terminati da un carattere null ( \0
) anziché da spazi bianchi e le virgolette e la barra rovesciata non sono speciali (ogni carattere è preso alla lettera)"
xargs -r
non verrà eseguitomv
se non ci sono file da spostare (ad es. se find
non sono stati trovati file).
--
termina l'elaborazione degli argomenti come opzioni per il programma, maggiori dettagli qui
Output di esempio (esegue un mv
comando e può gestire anche file con newline nel loro nome):
$ 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'
Per 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.
Per 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: Qualcuno ha detto che non avevano head -z
, questa è la versione che stavo usando (in 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
Per 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.
Per cp
:
-t, --target-directory=DIRECTORY
copy all SOURCE arguments into DIRECTORY
-v, --verbose
explain what is being done
Un'altra variante, ispirata a https://unix.stackexchange.com/a/105042/66736 :
cp `ls -d ./* | head -n 100` tmpi
Potrebbe non essere il modo più veloce o più elegante, ma è un modo che puoi tenere in memoria.
So che questa discussione è piuttosto vecchia, ma ho trovato le risposte più complicate di quanto pensassi che dovessero essere. Questo ha funzionato in CentOS, ma sembra abbastanza semplice che probabilmente dovrebbe funzionare in altre distro.
cp `ls someDir | head -n 100` someDir100/
ls
non include il somedir/
prefisso iniziale e non funziona per il nome file con caratteri vuoti o jolly o inizia con -
.
ls | head -n 100
../someDir100/ Dall'interno della directory di destinazione e nessuno dei nomi dei file ha soddisfatto quei casi. Meglio essere fortunati, allora bene!
about.com
e ad altri siti Web per l'elenco delle opzioni disponibili che posso eventualmente usare .. ma non ho trovato nulla di similetail