【问题标题】:Linux copy next 'n' number of files from one folder to another in bash/python scriptLinux在bash / python脚本中将下一个'n'个文件从一个文件夹复制到另一个文件夹
【发布时间】:2021-03-01 11:59:33
【问题描述】:

我们有 17k 个文件,其名称类似于 file1.csv、file2.csv、file3.csv ...file17000.csv。 所有这些文件都应该从一个文件夹复制到另一个文件夹。 目标是创建 Linux bash 或 python 脚本,以每 5 分钟复制所有这些文件除以“n”个 csv 文件,并防止复制“n”个已复制的文件。

想法是:

copy file1.csv file2.csv file3.csv  file4.csv  file5.csv to destination_dir
sleep for 300 seconds
copy file6.csv file7.csv file8.csv file9.csv file10.csv to destination_dir
sleep for 300 seconds
...
copy file16996.csv file16997.csv file16998.csv file16999.csv file17000.csv to destination_dir

对于少量文件,我们在下面的脚本中使用了在 2 个范围之间复制文件:

#!/bin/bash
source_dir='/source_dir'
target_dir='/target_dir'
echo "beginning number:$1"
echo $1
echo "finite number:$2"
echo $2
for f in $(eval ls $source_dir/file{$1..$2}.csv);
do
cp $f $target_dir
done

谁能建议如何正确指向脚本以使用下一个“n”个 csv 文件

任何意见和建议将不胜感激。

【问题讨论】:

    标签: python linux shell file copy


    【解决方案1】:

    这有帮助吗?

    import os, os.path
    import time
    
    from shutil import copyfile
    
    def copy_n_files(src, dest, n, start=0):
        for file_num in range(start, start+n):
            copyfile(f"{src}/file{i}.csv", dst)
    
    SRC_DIR = "src"
    DEST_DIR = "dest"
    
    
    num_files = len([f for f in os.listdir(path)if os.path.isfile(os.path.join(path, f)) and f.endswith(".csv")])
    step_size = 10 # number of files you want to copy in one go
    sleep_time = 300 # nunmber of seconds you want to sleep for
    
    for i in range(0, num_files, step_size):
        copy_n_files(SRC_DIR, DEST_DIR, step_size, i)
        time.sleep(sleep_time)
    
    

    【讨论】:

      【解决方案2】:

      使用 bash:

      max=$(for i in printf file*.csv;do echo $i;done | grep -Eo '[[:digit:]]+' | tail -1)  # Work out the maximum file number
      n=5                                                                                   # Set the batch number of files to copy in one go
      for ((i=1;i<=max;i=i+$n));                                                            # Loop from one to max file in batches of n
      do 
        sleep 300
        p=$(($i+($n-1)));                                                                   # Set the upper limit for batch file copying
        for ((k=i;i<=p;k++));
        do
           cp "file$k.csv" destination_dir                                                  # Copy files using lower and upper limits of files for this pass
        done
      done
      

      【讨论】:

        【解决方案3】:

        一个 bash 版本,随心所欲地添加 batch_size 变量

        #!/bin/bash
        source_dir='/source_dir'
        target_dir='/target_dir'
        
        all_csv_files=`ls -1v $source_dir/file*.csv`
        batch_size=5
        sleep_break=300
        
        file_counter=0
        echo Found ${#all_csv_files[@]} files
        
        for f in "${all_csv_files[@]}"
        do
            cp $f $target_dir
            let file_counter++
            if [ $file_counter == $batch_size ] 
            then
                echo Take a break `date`
                file_counter=0
                sleep $sleep_break
            fi
        done
        
        echo Done
        

        【讨论】:

        • 谢谢你,马塞尔!您的脚本帮助了我,但不知何故,脚本使用 file10000.csv 作为复制的初始编号。我要在脚本中更改的一件事是,将 file1.csv 设置为复制的初始编号。
        • @RavilKhalilov,对文件进行数字排序的一种解决方案是all_csv_files=`ls -1v $source_dir/file*.csv `。答案已更新
        • 嗨马塞尔,谢谢你的建议。抱歉回复晚了,我一直在忙另一个项目。我使用了你的脚本,但不幸的是,脚本复制了文件夹中找到的所有文件,而不是每批复制 5 个文件,即使我们有一个名为 batch_size=5 的参数。
        【解决方案4】:

        最后,我们通过更新 Marcel 提供的脚本来完成。 我们添加了 while 函数来读取数组中的文件列表,它可以按预期工作:

        #!/bin/bash
        all_csv_files=()
        source_dir='/source_dir'
        target_dir='/target_dir'
        while IFS=  read -r -d $'\0'; do
            all_csv_files+=("$REPLY")
        done < <(find $source_dir -name "file*.csv" -print0)
        
        echo ${#all_csv_files[@]}
        
        batch_size=5
        sleep_break=60
        file_counter=0
        
        echo Found ${#all_csv_files[@]} files
        
        for f in "${all_csv_files[@]}"
        do
            cp $f $target_dir
            echo $f
            let file_counter++
            if [ $file_counter == $batch_size ]
            then
                echo "Take a break $(date)"
                file_counter=0
                sleep $sleep_break
            fi
        done
        echo Done
        

        谢谢大家的建议!

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2013-11-20
          • 1970-01-01
          • 1970-01-01
          • 2023-01-14
          • 2019-06-23
          • 1970-01-01
          • 2017-03-01
          • 2011-08-22
          相关资源
          最近更新 更多