수천을 포함하는 폴더에서 100 개의 파일을 이동하는 방법?


43

수천 개의 파일이있는 디렉토리가 있습니다. 100 개의 파일 (모든 파일)을 다른 위치로 옮기려면 어떻게해야합니까?


단순히 같은 웹 사이트로 이동 있도록 유닉스와 리눅스는 그 도구에 대한 하나 개의 큰 웹 사이트를 가지고 있겠지 때문에 about.com내가 가능성이 사용할 수있는 사용 가능한 옵션 목록에 대한 몇 가지 다른 웹 사이트 ..하지만 같이 아무것도 찾을 수 없습니다tail
이징

답변:


37
for file in $(ls -p | grep -v / | tail -100)
do
mv $file /other/location
done

즉 파일 이름은 줄 바꿈 (기본값 가정에 공백이 포함되지 않은 가정 $IFS), 와일드 카드 문자 ( ?, *, [) 또는 시작 -.


12
이 접근 방식은 파일 이름에 특수 문자 (공백, 인쇄 할 수없는 문자,``)가없는 경우에만 작동합니다. 일반적으로 의 출력을 구문 분석하지 마십시오ls . 그리고 항상 매개 변수 및 명령 대체를 큰 따옴표로 묶습니다.
Gilles 'SO- 악마 그만'

1
어느 부분이 100 개의 파일을 차지합니까?
tshepang

3
내 이전 의견으로 업데이트 : Gilles의 참조 링크를 읽은 후 ls 출력을 구문 분석하지 마십시오find . 내 명령이 부족하다는 것을 알았습니다 . arg가 잘못된 위치에 있었고 null 파일 이름 끝을 추가했습니다. 한 줄로 조금 길지만 주석으로 할 수있는 전부입니다. 다음은 고정 된 스 니펫입니다.find . -maxdepth 1 -type f \( ! -iname ".*" \) -print0 | while read -rd $'\0' file ; do mv -- "$file" /other/location/ ; done
Peter.O

@perer read -d옵션이 모든 쉘에 이식 가능하지는 않지만 bash어쨌든 사용 -d ''하는 경우와 동일한 효과를 얻을 수 있습니다 -d $'\0'.
jw013

이것을 하나의 라이너로 실행하려면 ;각 줄 바꿈이 있는 곳에 추가하십시오 .
패트릭

37

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을 제외한 모든 것을 제거하는 것 입니다.


안전한 쉘 확장을 위해 +1 증가 작업 $(( i++ ))이나 $[ i++ ]? 로 더 읽기 쉽습니다 .

2
@hesse 일부 쉘은 구현하지 않는 ++--. : $((i+=1))대신 쓸 수 있습니다 i=$((i+1)); 더 읽기 쉽다고 확신하지 않습니다.
Gilles 'SO- 악마 그만'

1
:-D, 나는 실제로이 답변을 내 생각으로 편집했습니다 ... 죄송합니다. 의미가 바뀌므로 자유롭게 되 돌리십시오.
Stéphane Chazelas

@ StéphaneChazelas 왜 디렉토리와 심볼릭 링크를 제외 시킬지 궁금합니다.
Gilles 'SO- 악마 그만해'

@ Giles, 받아 들인 대답은 ls -p | grep -v /여기에 빠진 최근 질문이 있습니다.
Stéphane Chazelas

8

zsh를 사용하지 않는 경우 :

set -- *
[ "$#" -le 100 ] || shift "$(($# - 100))"
mv -- "$@" /target/dir

마지막 (알파벳 순서로) 100을 움직입니다.


3

쉘의 다음 oneliner가 도움이 될 것입니다.

foreach i (`발견 Source_Directory -type f --max-depth 1 | tail -100`); 하다; {mv $ i Target_Directory}; 끝난

1
그게 뭐야?
phk

@phk, 그것은 zsh언뜻보기에는 zsh구문에 외계인처럼 보이지만 작동 할 것 입니다. Gilles는이 작업을 수행하는 훨씬 간단한 방법을 보여주었습니다 zsh. 그럼에도 불구하고, 그것은 현재 받아 들여지는 대답보다 여전히 신뢰할 만합니다.
Stéphane Chazelas

3

다음은 나를 위해 일했습니다. 이전에 게시 한 경우 죄송하지만 빠른 스캔에서 보지 못했습니다.

ls path/to/dir/containing/files/* | head -100 | xargs -I{} cp {} /Path/to/new/dir


1

mmv 는 파일의 대량 이름 바꾸기를 수행 할 수있는 뛰어난 유틸리티입니다. (나는에 있었다 sudo apt-get install mmv설치 내 컴퓨터에.) 간단한 사용 예 : 당신은 당신이 소문자 .JPG로 변경하고 싶은 것을 확장 .JPG 가진 파일의 디렉토리가 있다고 가정합니다. 다음 명령은 트릭을 수행합니다.

mmv \*.JPG \#1.jpg

백 슬래시는 와일드 카드가오고 있음을 나타내는 데 사용됩니다. * / JPG는 JPG 확장명과 일치합니다. 명령의 "to"부분에서 # 1은 첫 번째 와일드 카드의 일치하는 텍스트를 사용하여 파일 이름을 바꿉니다. 물론 # 1 앞에 다른 경로를 넣어 파일을 이동할 수도 있습니다.


2
목표를 달성하기 위해 제안한 도구를 실제로 사용하는 방법을 제공하면 더 유리할 것입니다.
Dason

1
사용 예 추가
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

이 코드를 사용해보십시오


0

이 시도:

find /source/directory -type f -maxdepth 1 -print | tail -100 | xargs -J % mv % /other/location/

이것은 정확하지 않습니다.에 세 개의 인수를 전달 mv합니다. 마지막 인수 는 아마도 디렉토리가 아닙니다. 그리고 그것은 실제로 질문에 답하지 않습니다-asker는 모든 파일이 아니라 주어진 수의 파일을 옮기기를 원합니다.
Mat

명령이 업데이트되었습니다.
Saumil

0

나는 여기에 왔지만 파일을 (99 개) 부분에서에서 (으)로 복사해야 /DIR1했습니다 /DIR2. otherz를 돕기 위해 스크립트를 여기에 붙여 넣을 것입니다.

#!/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

0

사용에 관심이 있다면 다음 명령이 작동합니다. ls

$ ls -rt source/* | head -n100 | xargs cp -t destination

어떻게 작동합니까 ??

  • ls -rt source/* -명령은 상대 경로와 함께 모든 파일을 나열합니다
  • head -n100 -처음 100 개의 파일을 가져옵니다
  • xargs cp -t destination -이 파일들을 대상 폴더로 옮깁니다.

0

공백, 줄 바꿈, 따옴표, 백 슬래시 등으로 파일 이름을 안전하게 보호하고 처리하려면 null로 끝나는 구분 기호를 사용해야합니다.

find "$srcdir" -maxdepth 1 -type f -print0 | head -z -n 100 | xargs -0 -r -- mv -t "$destdir" --

EDIT2 : 참고 : 당신이하지 않은 경우 head -z( 어떤 이유 ) 위의를 대체 할 수 head -z -n 1000tr '\0\n' '\n\0' | head -n 1000 | tr '\0\n' '\n\0'(또는 다른 방법을 참조 )

-maxdepth 1의 하위 디렉토리에있는 파일을 찾지 $srcdir않으므로 나열된 유일한 파일은에있는 파일입니다 $srcdir. 나열된 각 파일 사이 에 줄 바꿈 ( ) 대신
-print0사용 \0-xargs로 줄 \n바꿈과 공백이 포함 된 파일을 처리하는 데 도움이됩니다.
head -z카운트한다 \0말단 (대신 개행 ( \n선으로 라인) 종료). 찾은 -n 100첫 번째 100파일 만 나열합니다 find.
어떤 명령 xargs이 실행 되는지 확인 하려면 -t(또는 --verbose)를 추가하십시오 .
xargs -0"입력 항목은 \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

-1

나는이 스레드가 꽤 오래되었다는 것을 알고 있지만 대답이 생각보다 복잡하다는 것을 알았습니다. 이것은 CentOS에서 작동했지만 다른 배포판에서 작동 할 정도로 간단 해 보입니다.

cp `ls someDir | head -n 100` someDir100/

1
출력 ls에는 선행 somedir/접두사가 포함되지 않으며 공백이나 와일드 카드 문자가 포함 된 파일 이름 또는로 시작 하지 않기 때문에 작동하지 않습니다 -.
Stéphane Chazelas

그럴 수 있지. 실제로 ls | head -n 100대상 디렉토리 내부에서 cp ../someDir100/ From을 수행했으며 파일 이름 중 어느 것도 그러한 경우를 만족시키지 못했습니다. 운이 좋으면 좋을 것 같아요!
Jason
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.