首页 > 解决方案 > 如何根据文件的数量将文件夹的内容复制到多个文件夹?

问题描述

我想根据文件的数量(这里:50)将文件从一个文件夹(名为:1)复制到多个文件夹。

下面给出的代码有效。我根据文件的数量将所有文件从文件夹转移到子文件夹,然后将目录中的所有文件复制回初始文件夹。但是,我需要更清洁、更高效的东西。为下面的混乱道歉,我是一个nube。

bf=1 #breakfolder
cd 1 #the folder from where I wanna copy stuff, contains 179 files

flies_exist=$(ls -1q * | wc -l) #assign the number of files in folder 1

#move 50 files from 1 to various subfolders

while [ $flies_exist -gt 50 ]
do

mkdir ../CompiledPdfOutput/temp/1-$bf
set --
for f in .* *; do
  [ "$#" -lt 50 ] || break
  [ -f "$f" ] || continue
  [ -L "$f" ] && continue
  set -- "$@" "$f"
done

mv -- "$@" ../CompiledPdfOutput/temp/1-$bf/
flies_exist=$(ls -1q * | wc -l)
bf=$(($bf + 1))
done

#mover the rest of the files into one final subdir

mkdir ../CompiledPdfOutput/temp/1-$bf
set --
for f in .* *; do
  [ "$#" -lt 50 ] || break
  [ -f "$f" ] || continue
  [ -L "$f" ] && continue
  set -- "$@" "$f"
done
mv -- "$@" ../CompiledPdfOutput/temp/1-$bf/
#get out of 1
cd ..

# copy back the contents from subdir to 1
find CompiledPdfOutput/temp/ -exec cp {} 1 \;

所需的目录结构是:

        parent
  ________|________
  |               |
  1       CompiledPdfOutput
  |               |
(179)           temp
                  |
             ---------------
             |    |    |    |
            1-1  1-2  1-3  1-4
            (50) (50) (50) (29)

“()”中的数字表示文件的数量。

顺便说一句,我的代码的最后一步给出了这个警告,如果有人能解释正在发生的事情和解决方案,我会很高兴。

cp: -r not specified; omitting directory 'CompiledPdfOutput/temp/'
cp: -r not specified; omitting directory 'CompiledPdfOutput/temp/1-4'
cp: -r not specified; omitting directory 'CompiledPdfOutput/temp/1-3'
cp: -r not specified; omitting directory 'CompiledPdfOutput/temp/1-1'
cp: -r not specified; omitting directory 'CompiledPdfOutput/temp/1-2'

我也不想复制目录,只是提供 -r 的文件会很糟糕。

标签: linuxbash

解决方案


假设您需要更紧凑/更高效的东西,您可以利用现有工具(find、xargs)来创建管道,从而无需使用 bash 对每个步骤进行编程。

以下将文件移动到拆分文件夹中。它将找到文件,将它们分组,每个文件夹 50 个,使用 awk 生成输出文件夹,然后移动文件。解决方案不如原来的优雅:-(

find 1 -type f |
    xargs -L50 echo |
    awk '{ print "CompliedOutput/temp/1-" NR, $0 }' |
    xargs -L1 echo mv -t

作为旁注,当前脚本将文件从“1”文件夹移动到编号文件夹,然后将文件复制回原始文件夹。为什么不直接将文件复制到编号的文件夹中。如果需要,您可以使用“cp -p”来保留时间戳。

支持带有新行(和空格)的文件名

澄清问题表明解决方案应使用嵌入新行(和空格)的文件名。这需要稍作更改以使用 NUL 字符作为分隔符。

  # Count number of output folders
DIR_COUNT=$(find 1 -type f -print0 | xargs -0 -I{} echo X | wc -l)
  # Remove previous tree, and create folder
OUT=CompiledOutput/temp
rm -rf $OUT
eval mkdir -p $OUT/1-{1..$DIR_COUNT}

# Process file, use NUL as separator
find 1 -type f -print0 | 
   awk -vRS="\0"  -v"OUT=$OUT" 'NR%50 == 1 { printf "%s/1-%d%s",OUT,1+int(NR/50),RS } { printf "%s", ($0 RS) }' |
   xargs -0 -L51 -t mv -t

对文件中的空格和新行进行了有限的测试。在我的机器上看起来不错。


推荐阅读