最近因爲工作的需要以及老大的要求,需要將每次提交到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。