基于文件列表批量拷贝文件

        最近因为工作的需要以及老大的要求,需要将每次提交到SVN的文件拷贝到另外一台电脑上,本来在那台电脑上搭建SVN就可以很好的解决这个问题。但是老大不同意,只能自己将修改的文件一个个拷贝过去。搞了几天感觉耗费了不少时间,而且把时间花在这个方面真的很不值得。老大也叫我想办法开发个工具来提高工作效率,学习的最终目的在于实践。于是用所学的知识开发了一个工具。有Shell脚本和C++两种方式实现的。

        假设我们获取了文件列表并将其保存在一个txt文件中。

<span style="font-size:18px;">/usr/test
/home/Richard/test
mate-screensaver
mate-screensaver-command
mate-screensaver-preferences
mate-screenshot
mate-search-tool
mate-session
mate-session-properties
mate-session-save
mate-settings-daemon
mate-system-log
mate-system-monitor</span>

        /usr/test是源目录,/home/Richard/test是目标目录,下面的就是待拷贝的文件。
        接下来我们要做的工作就是将源目录中的指定文件拷贝到目标目录中。

        学过Linux的同学都知道可以使用mkdir 来创建目录,使用cp命令来拷贝文件。下面就贴出Shell脚本

<span style="font-size:18px;">#!/bin/bash
FILENAME="$1"
count=0
SrcBaseDir=""	#源目录
DstBaseDir=""	#目标目录
PureFileName=""	#文件名,对应于文件列表中的每一行
SrcFullFileName=""	#源文件全路径
DstFullFileName=""  #目标文件全路径

#拷贝文件
function CopyFiles()
{
 while read LINE
do
{
	count=$[ $count + 1 ]
	if [ $count -eq 1 ] 
	then
		SrcBaseDir=$LINE

		if [ ! \( -e $SrcBaseDir \) ]
		then
			break
		fi

		if test ${SrcBaseDir#${SrcBaseDir%?}} != "/"
		then
			SrcBaseDir=${SrcBaseDir}"/"
		fi
	elif [ $count -eq 2 ]
	then
		#判断目录是否存在,不存在则创建,并在目录后面加/
		DstBaseDir=$LINE

		if [ ! \( -e $DstBaseDir \) ]
		then
			mkdir -p $DstBaseDir
		fi

		if test ${DstBaseDir#${DstBaseDir%?}} != "/"	#判断结尾是否有/
		then
			DstBaseDir=${DstBaseDir}"/"
		fi
	else
		PureFileName=$LINE		#文件名
		if test ${PureFileName:1:1} = "/"
		then
			PureFileName=${PureFileName#*/}				#去掉开头的/
		fi

		SrcFullFileName=${SrcBaseDir}${PureFileName}	#源文件完整路径名
		DstFullFileName=${DstBaseDir}${PureFileName}	#目标文件完整路径名
		echo $SrcFullFileName
		echo $DstFullFileName

		#判断源文件是否存在,不存在则创建
		if [ ! \( -e $SrcFullFileName \) ]
		then
			if [ ${SrcFullFileName#${SrcFullFileName%?}} = "/" ] 
			then
				mkdir -p $SrcFullFileName
			else
				ParentDir=${SrcFullFileName%/*}
				if [ ! \( -e $ParentDir \) ]
				then
					mkdir -p $ParentDir
				fi
				touch $SrcFullFileName 
			fi
		fi

		#判断目标文件是否存在,
		if [ ! \( -e $DstFullFileName \) ]
		then
			if [ ${DstFullFileName#${DstFullFileName%?}} = "/" ] 
			then
				mkdir -p $DstFullFileName
			else
				ParentDir=${DstFullFileName%/*}
				if [ ! \( -e $ParentDir \) ]
				then
					mkdir -p $ParentDir
				fi
				cp $SrcFullFileName $ParentDir
			fi
		else
			if [ ! \( -d $DstFullFileName \) ]
			then
				cp $SrcFullFileName ${DstFullFileName%/*}
			fi
		fi
	fi
}
done < $FILENAME
}

#删除临时文件
function DelTempFiles()
{
	if [ -e $1 ]
	then
		for FileName in `find $1`
		do
			if [ ${FileName#$FileName%?}} = '~' ]
			then
				rm -rf $FileName
			fi
		done
	fi
}

CopyFiles
DelTempFiles $SrcBaseDir
DelTempFiles $DstBaseDir
</span>


调用: ./copyfiles.sh test.txt

下面是C++的实现代码:

<span style="font-size:18px;">#include <boost/filesystem.hpp>
#include <iostream>
#include <fstream>
#include <vector>
#include <algorithm>

using namespace boost::filesystem;
using namespace std;

int main(int argc, char **argv)
{
    if (argc <= 1)
    {
        cout << "please specify the file list name!" << endl;
        return 0;
    }

    if (!is_regular_file(argv[1]))
    {
        cout << "It's not a regular file or file does not exists!" << endl;
        return 0;
    }

    vector<string> VecFiles;
    ifstream File(argv[1]);
    copy(istream_iterator<string>(File), istream_iterator<string>(), back_inserter(VecFiles));

    copy(VecFiles.begin(), VecFiles.end(), ostream_iterator<string>(cout, "\n"));
    File.close();

    if (VecFiles.size() <= 2)
    {
        cout << "No files need to copy" << endl;
        return 0;
    }

    if (VecFiles[0].find(':') != 1 && VecFiles[0].find('/') != 0)
    {
        cout << "Basic source path is not right!" << endl;
        return 0;
    }

    if (VecFiles[1].find(':') != 1 && VecFiles[1].find('/') != 0)
    {
        cout << "Basic destination path is not right!" << endl;
        return 0;
    }
    
    for (vector<string>::iterator it = VecFiles.begin() + 2; it != VecFiles.end(); ++it)
    {
        path FromPath(VecFiles[0]);
        path ToPath(VecFiles[1]);

        FromPath /= (*it);
        ToPath /= (*it);
        if (is_directory(FromPath))
        {
            if (!is_directory(ToPath))
            {
                create_directories(ToPath);
            }
        }
        else
        {
            if (!is_directory(ToPath.parent_path()))
            {
                create_directories(ToPath.parent_path());
            }
            copy_file(FromPath, ToPath, copy_option::overwrite_if_exists);
        }
    }

    return 0;
}</span>


       该程序是基于命令行的,调用:copyfiles test.txt

       感觉用Shell做的还是有些复杂,Shell中很多关于字符串操作的函数都很晦涩难懂,我用的是POSIX Parameter Expansions,而且Shell脚本的语法也很怪异。C++就不同了,可以直接将boost中的那些类拿过来用,有了它们就可以少写很多代码。当然前提是你的电脑上要安装boost库,我使用的是boost 1.55.0,是最新版本的,开发环境是Visual Studio 2010。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值