如何从包含数千个文件夹的文件夹中移动100个文件?


43

我有一个包含数千个文件的目录。如何将100个文件(任何文件都可以)移动到另一个位置。


因为Unix和Linux在其工具上没有一个大型网站,所以我只是去like网站about.com和其他网站以获取我可以使用的可用选项列表..但是什么都没找到tail
gaijin

Answers:


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

它假定文件名称不包含空格,换行(假定的默认值$IFS),通配符(?*[)或启动-


12
请注意,仅当文件名中没有特殊字符(空格,不可打印字符,``'')时,此方法才有效。一般而言,请勿解析的输出ls。并且总是双引号参数和命令替换。
吉尔斯(Gilles)'所以

1
哪一部分占100个文件?
tshepang

3
更新至我之前的评论:阅读了Gilles的参考链接后,不要解析ls的输出,我发现我的find命令缺失了。arg在错误的位置,并且我添加了空文件名结尾。一行很长,但这就是我在注释中所能做的。这是固定的代码段:find . -maxdepth 1 -type f \( ! -iname ".*" \) -print0 | while read -rd $'\0' file ; do mv -- "$file" /other/location/ ; done
Peter.O,

@perer请注意,该read -d选项并非可移植到所有shell,但如果您仍在使用bash-d ''则应获得与相同的效果-d $'\0'
jw013 2011年

FWIW如果要使其作为一个单行运行,请;在每个换行符现在的位置添加一个。
帕特里克

37

在zsh中最简单:

mv -- *([1,100]) /other/location/

这使第一100非隐藏文件(任何类型的,变化([1,100])(.[1,100])普通文件只,或(^/[1,100])任何类型的,但目录)的名称字典顺序。您可以使用o glob限定符选择其他排序顺序,例如,移动最旧的100个文件:

mv -- *(Om[1,100]) /other/location/

使用其他shell,您可以循环退出并提早退出。

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有些shell无法实现++--。您可以写: $((i+=1))而不是i=$((i+1)); 我不认为它更具可读性。
吉尔斯(Gillles)“所以-别再作恶了”

1
:-D,我实际上编辑了这个答案,以为那是我的...对不起。随意还原,因为这会改变含义。
斯特凡Chazelas

@StéphaneChazelas我确实想知道为什么您要排除目录和符号链接,这个问题什么也没说。
吉尔斯(Gillles)“所以-别再邪恶了”

@Gilles,已接受的答案也ls -p | grep -v /有一个最近的问题在这里出现。
斯特凡Chazelas

8

如果您不使用zsh:

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

将最后一个(按字母顺序)移动100个。


3

以下在shell中的oneliner会有所帮助。

foreach i(`找到Source_Directory -type f --max-depth 1 | tail -100`); 做; {mv $ i Target_Directory}; 做完了

1
那壳是什么?
phk

@phk,zsh即使乍一看看起来与zsh语法完全无关,它也可能会起作用。吉尔斯(Gilles)展示了一种更简单的方法zsh。即使这样,它仍然比当前接受的答案更可靠。
斯特凡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
如果您提供了如何实际使用建议的工具来实现目标,则将更加有益。
戴森

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,最后一个(可能)不是目录。它并没有真正回答问题-询问者想要移动给定数量的文件,而不是全部。
马太福音

命令已更新。
索米尔2012年

0

我是从这里来的,但是我需要从/DIR1到部分复制文件(每个文件99个)/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

如果要安全/处理包含空格,换行符,引号,反斜杠等的文件名,则必须使用以空字符结尾的分隔符:

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而不是newline(\n)-这有助于使用xargs处理包含换行符和空格的文件。
head -z\0终止行(而不是以newline(\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/前缀,并且不适用于带有空白或通配符或以开头的文件名-
斯特凡Chazelas

很公平。我实际上是ls | head -n 100从目标目录中执行cp ../someDir100/的,没有文件名可以满足这些情况。更好的是幸运然后好!
杰森
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.