Ponieważ Unix i Linux nie mają jednej dużej strony internetowej o swoich narzędziach, po prostu przechodzę do strony podobnej do about.comi innej strony z listą dostępnych opcji, których mogę ewentualnie użyć ... ale nic nie znalazłemtail
gaijin
Odpowiedzi:
37
for file in $(ls -p | grep -v / | tail -100)
do
mv $file /other/location
done
Zakłada, że nazwy plików nie zawierają spacje, nowej linii (przy założeniu, że wartość domyślna $IFS), symbole wieloznaczne ( ?, *, [) lub zacząć -.
Zauważ, że to podejście działa tylko wtedy, gdy w nazwach plików nie ma znaków specjalnych (białe znaki, znaki niedrukowalne, ``). Zasadniczo nie analizuj danych wyjściowychls . I zawsze podwójne cytowanie podstawień parametrów i poleceń.
Gilles „SO- przestań być zły”
1
Która część stanowi 100 plików?
tshepang
3
Zaktualizuj mój poprzedni komentarz: Po przeczytaniu linku referencyjnego Gillesa nie analizuj danych wyjściowych ls , zauważyłem, że findbrakuje mojej komendy. Argument był w niewłaściwym miejscu, a ja dodałem puste nazwy plików. Jest to nieco długi wiersz, ale to wszystko, co mogę zrobić w komentarzu. Oto naprawiony fragment:find . -maxdepth 1 -type f \( ! -iname ".*" \) -print0 | while read -rd $'\0' file ; do mv -- "$file" /other/location/ ; done
Peter.O
@perer Tak jak należy zauważyć, że read -dopcja nie jest przenośna dla wszystkich powłok, ale jeśli mimo to używasz bash, -d ''powinna dać ci taki sam efekt jak -d $'\0'.
jw013,
FWIW, jeśli chcesz, aby działało to jako oneliner, dodaj miejsce, w ;którym znajduje się teraz każda nowa linia.
Patrick
37
Najłatwiej jest w Zsh:
mv -- *([1,100]) /other/location/
To przenosi pierwsze 100 nie ukrytych plików (dowolnego typu, zmień ([1,100])na tylko (.[1,100])dla zwykłych plików lub (^/[1,100])dla dowolnego typu poza katalogiem ) w kolejności leksykograficznej. Możesz wybrać inną kolejność sortowania za pomocą okwalifikatora glob , np. Aby przenieść 100 najstarszych plików:
mv -- *(Om[1,100]) /other/location/
Z innymi pociskami możesz to zrobić w pętli z wczesnym wyjściem.
i=0
for x in *; do
if [ "$i" = 100 ]; then break; fi
mv -- "$x" /other/location/
i=$((i+1))
done
@phk, działałoby to zshnawet, gdyby na pierwszy rzut oka wyglądało to zupełnie obco zsh. Gilles pokazał znacznie prostszy sposób, aby to zrobić zsh. Nawet wtedy jest to bardziej wiarygodne niż obecnie akceptowana odpowiedź.
Stéphane Chazelas,
3
Poniższe działało dla mnie. Przepraszam, jeśli został opublikowany wcześniej, ale nie zobaczyłem go w szybkim skanie.
ls path/to/dir/containing/files/* | head -100 | xargs -I{} cp {} /Path/to/new/dir
mmv to wyjątkowe narzędzie, które pozwala także na masową zmianę nazw plików. (Musiałem sudo apt-get install mmvgo zainstalować na komputerze). Prosty przykład użycia: załóżmy, że masz katalog plików z rozszerzeniem .JPG, który chciałbyś zmienić na małe .jpg. Następujące polecenie załatwia sprawę:
mmv \*.JPG \#1.jpg
Ukośnik odwrotny służy do pokazania, że zbliża się symbol wieloznaczny. * / JPG pasuje do wszystkiego z rozszerzeniem JPG. W części polecenia „do” numer 1 używa pasującego tekstu z pierwszego symbolu wieloznacznego do zmiany nazwy pliku. Oczywiście możesz umieścić inną ścieżkę przed numerem 1, aby również przenieść plik.
Byłoby bardziej korzystne, gdybyś podał, w jaki sposób faktycznie skorzystasz z narzędzia, które sugerujesz, aby osiągnąć cel.
Dason
1
dodano przykład użycia
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
Jest to niepoprawne, przekazujesz trzy argumenty mv, z których ostatni (prawdopodobnie) nie jest katalogiem. I tak naprawdę nie odpowiada na pytanie - pytający chce przenieść określoną liczbę plików, a nie wszystkie.
Mat
Polecenie zaktualizowane.
Saumil
0
Przyszedłem tutaj, ale musiałem kopiować pliki w częściach (99 każda) od /DIR1do /DIR2. Wkleję tutaj skrypt, aby pomóc innym:
#!/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
Jeśli chcesz być bezpieczny / obsługiwać nazwy plików ze spacjami, znakami nowej linii, cudzysłowami, ukośnikami odwrotnymi itp., Musisz użyć separatorów zakończonych znakiem zerowym:
EDIT2: UWAGA: jeśli nie masz head -z( niezależnie od przyczyny ) można zastąpić wyżej head -z -n 1000z tr '\0\n' '\n\0' | head -n 1000 | tr '\0\n' '\n\0'(lub zobaczyć inne sposoby )
-maxdepth 1uniknie szukania plików w podkatalogach $srcdir, więc jedynymi wymienionymi są pliki wewnątrz $srcdir. -print0użyje \0zamiast newline ( \n) między każdym wymienionym plikiem - pomaga to obsługiwać pliki zawierające znaki nowej linii i spacje za pomocą xargs. head -zbędzie liczyć \0zakończone (zamiast zakończone newline \n) linie jako linie. -n 100wyświetli tylko pierwsze znalezione 100pliki find.
Jeśli chcesz zobaczyć, które polecenie xargszostanie wykonane, dodaj -t(lub --verbose). xargs -0„Elementy wejściowe są zakończone znakiem null ( \0) zamiast spacją, a cudzysłowy i ukośnik odwrotny nie są wyjątkowe (każdy znak jest traktowany dosłownie)” xargs -rnie będzie działaćmvjeśli nie ma żadnych plików do przeniesienia (tj. jeśli findnie znalazł żadnych plików). --kończy przetwarzanie argumentów jako opcji programu, więcej szczegółów tutaj
Przykładowe dane wyjściowe (uruchamia jedno mvpolecenie i może również obsługiwać pliki z nową linią w nazwie):
$ 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'
Dla 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.
Dla 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
EDYCJA: Ktoś wspomniał , że nie ma head -z, to jest wersja, której używałem (w Fedorze 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
Dla 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.
Dla cp:
-t, --target-directory=DIRECTORY
copy all SOURCE arguments into DIRECTORY
-v, --verbose
explain what is being done
Wiem, że ten wątek jest dość stary, ale znalazłem odpowiedzi bardziej skomplikowane, niż się spodziewałem. Działa to w CentOS, ale wydaje się na tyle proste, że prawdopodobnie powinno działać w innych dystrybucjach.
To nie działa, ponieważ wynik lsnie zawiera wiodącego somedir/przedrostka i nie będzie działać w przypadku nazw plików ze znakami pustymi lub znakami wieloznacznymi lub na początku -.
Stéphane Chazelas
Słusznie. Właściwie zrobiłem cp ls | head -n 100../someDir100/ Z wnętrza katalogu docelowego i żadna z nazw plików nie spełniała tych przypadków. Lepiej mieć szczęście, niż dobrze!
about.com
i innej strony z listą dostępnych opcji, których mogę ewentualnie użyć ... ale nic nie znalazłemtail
Odpowiedzi:
Zakłada, że nazwy plików nie zawierają spacje, nowej linii (przy założeniu, że wartość domyślna
$IFS
), symbole wieloznaczne (?
,*
,[
) lub zacząć-
.źródło
ls
. I zawsze podwójne cytowanie podstawień parametrów i poleceń.find
brakuje mojej komendy. Argument był w niewłaściwym miejscu, a ja dodałem puste nazwy plików. Jest to nieco długi wiersz, ale to wszystko, co mogę zrobić w komentarzu. Oto naprawiony fragment:find . -maxdepth 1 -type f \( ! -iname ".*" \) -print0 | while read -rd $'\0' file ; do mv -- "$file" /other/location/ ; done
read -d
opcja nie jest przenośna dla wszystkich powłok, ale jeśli mimo to używaszbash
,-d ''
powinna dać ci taki sam efekt jak-d $'\0'
.;
którym znajduje się teraz każda nowa linia.Najłatwiej jest w Zsh:
To przenosi pierwsze 100 nie ukrytych plików (dowolnego typu, zmień
([1,100])
na tylko(.[1,100])
dla zwykłych plików lub(^/[1,100])
dla dowolnego typu poza katalogiem ) w kolejności leksykograficznej. Możesz wybrać inną kolejność sortowania za pomocąo
kwalifikatora glob , np. Aby przenieść 100 najstarszych plików:Z innymi pociskami możesz to zrobić w pętli z wczesnym wyjściem.
Innym przenośnym sposobem byłoby zbudowanie listy plików i usunięcie wszystkich oprócz ostatnich 100 .
źródło
$(( i++ ))
lub$[ i++ ]
?++
i--
. Możesz pisać: $((i+=1))
zamiasti=$((i+1))
; Nie jestem przekonany, że jest bardziej czytelny.ls -p | grep -v /
ma również ostatnie pytanie, które tutaj się powtarza.Jeśli nie używasz zsh:
Przesunąłby ostatni (w kolejności alfabetycznej) 100.
źródło
Pomocny byłby następujący oneliner w powłoce.
źródło
zsh
nawet, gdyby na pierwszy rzut oka wyglądało to zupełnie obcozsh
. Gilles pokazał znacznie prostszy sposób, aby to zrobićzsh
. Nawet wtedy jest to bardziej wiarygodne niż obecnie akceptowana odpowiedź.Poniższe działało dla mnie. Przepraszam, jeśli został opublikowany wcześniej, ale nie zobaczyłem go w szybkim skanie.
źródło
Od https://stackoverflow.com/questions/14033129/how-to-move-a-given-number-of-random-files-on-unix-linux-os
źródło
mmv to wyjątkowe narzędzie, które pozwala także na masową zmianę nazw plików. (Musiałem
sudo apt-get install mmv
go zainstalować na komputerze). Prosty przykład użycia: załóżmy, że masz katalog plików z rozszerzeniem .JPG, który chciałbyś zmienić na małe .jpg. Następujące polecenie załatwia sprawę:Ukośnik odwrotny służy do pokazania, że zbliża się symbol wieloznaczny. * / JPG pasuje do wszystkiego z rozszerzeniem JPG. W części polecenia „do” numer 1 używa pasującego tekstu z pierwszego symbolu wieloznacznego do zmiany nazwy pliku. Oczywiście możesz umieścić inną ścieżkę przed numerem 1, aby również przenieść plik.
źródło
wypróbuj ten kod
źródło
Spróbuj tego:
źródło
mv
, z których ostatni (prawdopodobnie) nie jest katalogiem. I tak naprawdę nie odpowiada na pytanie - pytający chce przenieść określoną liczbę plików, a nie wszystkie.Przyszedłem tutaj, ale musiałem kopiować pliki w częściach (99 każda) od
/DIR1
do/DIR2
. Wkleję tutaj skrypt, aby pomóc innym:źródło
Poniższe polecenie działa, jeśli jesteś zainteresowany użyciem
ls
Jak to działa ??
ls -rt source/*
- polecenie wyświetla wszystkie pliki ze ścieżką względnąhead -n100
- pobiera pierwsze 100 plikówxargs cp -t destination
- przenosi te pliki do folderu docelowegoźródło
Jeśli chcesz być bezpieczny / obsługiwać nazwy plików ze spacjami, znakami nowej linii, cudzysłowami, ukośnikami odwrotnymi itp., Musisz użyć separatorów zakończonych znakiem zerowym:
EDIT2: UWAGA: jeśli nie masz
head -z
( niezależnie od przyczyny ) można zastąpić wyżejhead -z -n 1000
ztr '\0\n' '\n\0' | head -n 1000 | tr '\0\n' '\n\0'
(lub zobaczyć inne sposoby )-maxdepth 1
uniknie szukania plików w podkatalogach$srcdir
, więc jedynymi wymienionymi są pliki wewnątrz$srcdir
.-print0
użyje\0
zamiast newline (\n
) między każdym wymienionym plikiem - pomaga to obsługiwać pliki zawierające znaki nowej linii i spacje za pomocą xargs.head -z
będzie liczyć\0
zakończone (zamiast zakończone newline\n
) linie jako linie.-n 100
wyświetli tylko pierwsze znalezione100
plikifind
.Jeśli chcesz zobaczyć, które polecenie
xargs
zostanie wykonane, dodaj-t
(lub--verbose
).xargs -0
„Elementy wejściowe są zakończone znakiem null (\0
) zamiast spacją, a cudzysłowy i ukośnik odwrotny nie są wyjątkowe (każdy znak jest traktowany dosłownie)”xargs -r
nie będzie działaćmv
jeśli nie ma żadnych plików do przeniesienia (tj. jeślifind
nie znalazł żadnych plików).--
kończy przetwarzanie argumentów jako opcji programu, więcej szczegółów tutajPrzykładowe dane wyjściowe (uruchamia jedno
mv
polecenie i może również obsługiwać pliki z nową linią w nazwie):Dla
find
:Dla
head
:EDYCJA: Ktoś wspomniał , że nie ma
head -z
, to jest wersja, której używałem (w Fedorze 25):Dla
xargs
:Dla
cp
:źródło
Wiem, że ten wątek jest dość stary, ale znalazłem odpowiedzi bardziej skomplikowane, niż się spodziewałem. Działa to w CentOS, ale wydaje się na tyle proste, że prawdopodobnie powinno działać w innych dystrybucjach.
źródło
ls
nie zawiera wiodącegosomedir/
przedrostka i nie będzie działać w przypadku nazw plików ze znakami pustymi lub znakami wieloznacznymi lub na początku-
.ls | head -n 100
../someDir100/ Z wnętrza katalogu docelowego i żadna z nazw plików nie spełniała tych przypadków. Lepiej mieć szczęście, niż dobrze!