备份工具
实现一个特殊的备份工具bak(即创建bak.sh)
(1)备份命令格式:bak dir1 dir2
功能:将dir1中的所有文件(含子目录中的文件)备份到dir2目录,且将所有子目录以“-”连接
例如,dir1/a/b/c
文件将备份为dir2/a-b-c
(2)恢复命令格式:bak -x dir1 dir2
功能:将dir1
中的所有文件恢复到dir2目录,并还原备份前的目录结构
例如,bak -x dir2 dir3
,将原备份的文件恢复到一个新的目录dir3
请以附件中dic.tar
为例(dic.tar需先解包)进行验证。
附:34.1.4节 字符串操作
代码部分:
#!/bin/bash
# 如果参数个数为2一下, 直接退出脚本,
if [ $# -lt 2 ]; then
exit 1
fi
# 定义变量
string=""
current_parent_dir_name=""
flag=0
slash="/"
option="-x"
a="-"
# 不为还原选项
if [ ! $1 = $option ]; then
parent_dir_name=$1
ls -R $1 | while read line; do
# 获取父目录名字
if [ $flag -eq 0 ]; then
flag=1
length=${#line}
let length_1=$length-1
current_parent_dir_name=${line:0:$length_1}
else
file_name="$current_parent_dir_name$slash$line"
# 如果是普通文件
if [ -f $file_name ]; then
for (( i=0; i<${#current_parent_dir_name}; i++)); do
char=${current_parent_dir_name:$i:1}
if [ $char = $slash ]; then
char="-"
fi
string=${string}${char}
done
# 主目录下面拷贝过去, 直接拷贝
if [ $parent_dir_name = $string ]; then
string="$2$slash$line"
cp $file_name $string
# 子目录拷贝过去, 文件名改变
else
# 除去主目录的名称
string=${string:${#parent_dir_name}+1:${#string}}
# 目录名-文件名
string="${string}${a}${line}"
# 拷贝目录名 / 拷过去要改的名字
string="$2$slash$string"
cp $file_name $string
fi
# 如果是空 ""
elif [ ${#line} -eq 0 ]; then
flag=0
fi
string=""
fi
done
# 还原选项
elif [ $1 = $option ]; then
parent_dir_name=$3
index=0
ls $2 | while read line; do
for(( i=0; i<${#line}; i++)); do
char=${line:$i:1}
# echo "char=$char"
if [ $char = $a ]; then
array[$index]=$string
# echo "array[$index]=${array[$index]}"
let index=$index+1
string=""
else
string="$string$char"
fi
done
array[$index]=$string
# echo "array[$index]=${array[$index]}"
file_name=${array[$index]}
string=""
for (( i=0; i<$index; i++)); do
let s=$i-1
# 拼接成要还原的目录下的路径
if [ $i -eq 0 ]; then
string=$parent_dir_name$slash${array[$i]}
else
# echo "前: $string"
string=$string$slash${array[$i]}
# echo "后: $string"
fi
# echo "路径:$string"
# 目录不存在就创建
if [ ! -d $string ]; then
# echo "mkdir $string"
mkdir $string
fi
let j=$i+1
# 当前目录是最后一级目录
if [ ! $j -lt $index ]; then
# 除去文件前缀
length=0
for (( i=0; i<$index; i++)); do
if [ $i -eq 0 ]; then
let length=${#array[$i]}+length
else
let length=${#array[$i]}+length
let length=$length+1
fi
done
let length=$length+1
r=${line:$length:${#line}}
line=$2$slash$line
string=$string$slash$r
echo "cp $line $string"
cp $line $string
fi
done
if [ $index -eq 0 ]; then
line=$2$slash$line
# echo "cp $line $parent_dir_name$slash"
cp $line $parent_dir_name$slash
fi
string=""
index=0
done
fi
make&makefile
diction
是一个经典的Unix
小工具,用来检测使用不当的英文短语。请前往 http://www.gnu.org/software/diction/ 下载diction
源码包,(下载地址:http://ftp.gnu.org/gnu/diction/,diction-0.7.tar.gz)并完成:
(1) 按以下命令将diction
安装到当前目录
./configure --prefix=$PREFIX
make
make install
(其中,PREFIX
请先在当前目录创建dic
目录,并使用dic
目录的绝对路径)
测试diction
命令的使用,(测试用例请参考share/diction/C
中的短语)
(2) 请简要分析Makefile
文件(参考Makefile
使用指南 https://makefiletutorial.com/ )
答:
(1)软件安装
#1. 预备阶段
wy@ZeroJean:~/$ which gcc
/usr/bin/gcc
wy@ZeroJean:~/$ which clang
/usr/bin/clang
wy@ZeroJean:~/$ which make
/usr/bin/make
#2. 下载diction源码包,也可以通过访问网站下载上传安装源码包
wy@ZeroJean:~/$ ftp -p ftp.gnu.org
Name (ftp.gnu.org:anno): anonymous
ftp> cd gnu/diction
wy@ZeroJean:~/$ ls
diction-0.7.tar.gz
#3. 解压源码包
wy@ZeroJean:~/$ tar -xvf diction-0.7.tar.gz
diction-0.7/COPYING
diction-0.7/INSTALL
diction-0.7/Makefile.in
diction-0.7/README
diction-0.7/configure
diction-0.7/install-sh
diction-0.7/de
diction-0.7/en
diction-0.7/config.guess
diction-0.7/config.h.in
diction-0.7/config.sub
diction-0.7/configure.in
diction-0.7/diction-en.msg
diction-0.7/diction.1.in
diction-0.7/diction.c
diction-0.7/getopt.c
diction-0.7/getopt.h
diction-0.7/getopt1.c
diction-0.7/misc.c
diction-0.7/misc.h
diction-0.7/sentence-en.msg
diction-0.7/sentence.c
diction-0.7/sentence.h
diction-0.7/style-en.msg
diction-0.7/style.1
diction-0.7/style.c
wy@ZeroJean:~/diction$ ls
diction-0.7 diction-0.7.tar.gz
#4. 检查源码
wy@ZeroJean:~/$ tree diction-0.7
diction-0.7
├── config.guess
├── config.h.in
├── config.sub
├── configure
├── configure.in
├── COPYING
├── de
├── diction.1.in
├── diction.c
├── diction-en.msg
├── en
├── getopt1.c
├── getopt.c
├── getopt.h
├── INSTALL
├── install-sh
├── Makefile.in
├── misc.c
├── misc.h
├── README
├── sentence.c
├── sentence-en.msg
├── sentence.h
├── style.1
├── style.c
└── style-en.msg
0 directories, 26 files
#5. 生成程序 ./configure --prefix=$PREFIX,指定当前目录与目标目录
wy@ZeroJean:~/$cd diction-0.7
wy@ZeroJean:~/diction-0.7$ ./configure --prefix=../diction
loading cache ./config.cache
checking host system type... Invalid configuration `x86_64-pc-linux-gnuoldld': machine `x86_64-pc' not recognized
checking for gcc... gcc
checking whether the C compiler (gcc ) works... yes
checking whether the C compiler (gcc ) is a cross-compiler... no
checking whether we are using GNU C... yes
checking whether gcc accepts -g... yes
checking for a BSD compatible install... /usr/bin/install -c
checking for strerror... yes
checking for broken realloc... no
updating cache ./config.cache
creating ./config.status
creating Makefile #生成Makefile文件
creating config.h
wy@ZeroJean:~/diction-0.7$ ls -l
total 312
-rw-r--r-- 1 wy wy 1094 Jan 17 12:26 config.cache
-rwxr-xr-x 1 wy wy 20370 Aug 22 1998 config.guess
-rw-r--r-- 1 wy wy 194 Jan 17 12:26 config.h
-rw-r--r-- 1 wy wy 129 Aug 22 1998 config.h.in
-rw-r--r-- 1 wy wy 1674 Jan 17 12:26 config.log
-rwxr-xr-x 1 wy wy 7429 Jan 17 12:26 config.status
-rwxr-xr-x 1 wy wy 19236 Aug 22 1998 config.sub
-rwxr-xr-x 1 wy wy 41741 Aug 22 1998 configure
-rw-r--r-- 1 wy wy 848 Aug 22 1998 configure.in
-rw-r--r-- 1 wy wy 18043 Aug 22 1998 COPYING
-rw-r--r-- 1 wy wy 2118 Aug 22 1998 de
-rw-r--r-- 1 wy wy 4042 Aug 22 1998 diction.1.in
-rw-r--r-- 1 wy wy 10448 Aug 22 1998 diction.c
-rw-r--r-- 1 wy wy 795 Aug 22 1998 diction-en.msg
-rw-r--r-- 1 wy wy 19467 Aug 22 1998 en
-rw-r--r-- 1 wy wy 4510 Aug 23 1998 getopt1.c
-rw-r--r-- 1 wy wy 30140 Aug 23 1998 getopt.c
-rw-r--r-- 1 wy wy 4559 Aug 23 1998 getopt.h
-rw-r--r-- 1 wy wy 7832 Aug 22 1998 INSTALL
-rwxr-xr-x 1 wy wy 5585 Aug 22 1998 install-sh
-rw-r--r-- 1 wy wy 2008 Jan 17 12:26 Makefile
-rw-r--r-- 1 wy wy 1795 Aug 22 1998 Makefile.in
-rw-r--r-- 1 wy wy 845 Aug 22 1998 misc.c
-rw-r--r-- 1 wy wy 104 Aug 22 1998 misc.h
-rw-r--r-- 1 wy wy 1418 Aug 22 1998 README
-rw-r--r-- 1 wy wy 4597 Aug 22 1998 sentence.c
-rw-r--r-- 1 wy wy 120 Aug 22 1998 sentence-en.msg
-rw-r--r-- 1 wy wy 240 Aug 22 1998 sentence.h
-rw-r--r-- 1 wy wy 8905 Aug 22 1998 style.1
-rw-r--r-- 1 wy wy 17045 Aug 22 1998 style.c
-rw-r--r-- 1 wy wy 140 Aug 22 1998 style-en.msg
#6. 生成diction程序
wy@ZeroJean:~/diction-0.7$ make -v
GNU Make 4.3
Built for x86_64-pc-linux-gnu
Copyright (C) 1988-2020 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.
wy@ZeroJean:~/diction-0.7$ make
sed -e s+/usr/share+../diction/share+ diction.1.in >diction.1
wy@ZeroJean:~/diction-0.7$ tree
.
├── config.cache
├── config.guess
├── config.h
├── config.h.in
├── config.log
├── config.status
├── config.sub
├── configure
├── configure.in
├── COPYING
├── de
├── diction
├── diction.1
├── diction.1.in
├── diction.c
├── diction-en.msg
├── diction.o
├── en
├── getopt1.c
├── getopt1.o
├── getopt.c
├── getopt.h
├── getopt.o
├── INSTALL
├── install-sh
├── Makefile
├── Makefile.in
├── misc.c
├── misc.h
├── misc.o
├── README
├── sentence.c
├── sentence-en.msg
├── sentence.h
├── sentence.o
├── style
├── style.1
├── style.c
├── style-en.msg
└── style.o
0 directories, 40 files
#7. make install 安装
wy@ZeroJean:~/diction-0.7$ make install
/usr/bin/install -c -m 755 -d ../diction/bin
/usr/bin/install -c -s diction ../diction/bin/diction
/usr/bin/install -c -s style ../diction/bin/style
/usr/bin/install -c -m 755 -d ../diction/share/diction
/usr/bin/install -c -m 644 de ../diction/share/diction/de
/usr/bin/install -c -m 644 en ../diction/share/diction/en
(cd ../diction/share/diction; rm -f C; ln en C)
/usr/bin/install -c -m 755 -d ../diction/man/man1
/usr/bin/install -c -m 644 diction.1 ../diction/man/man1/diction.1
/usr/bin/install -c -m 644 style.1 ../diction/man/man1/style.1
#8. 查看目录结构并查看是否运行
wy@ZeroJean:~/diction-0.7$ tree ../diction
../diction
├── bin
│ ├── diction
│ └── style
├── man
│ └── man1
│ ├── diction.1
│ └── style.1
└── share
└── diction
├── C
├── de
└── en
5 directories, 7 files
wy@ZeroJean:~/diction-0.7$ which diction
/home/wy/diction/bin/diction #程序安装位置
(2):MakeFile文件结构
# Generated automatically from Makefile.in by configure.
VERSION= 0.7
srcdir= .
prefix= ../diction
exec_prefix= ${prefix}
BINDIR= ${exec_prefix}/bin
MANDIR= ${prefix}/man
SHAREDIR= ${prefix}/share
INSTALL= /usr/bin/install -c
INSTALL_PROGRAM=${INSTALL}
INSTALL_DATA= ${INSTALL} -m 644
CC= gcc #指定编译用的编辑器
CFLAGS= -g -O2 -g -Wmissing-prototypes -Wstrict-prototypes -Wcast-qual -Wpointer-arith -Wcast-align -Wwrite-strings -Wmissing-declarations -Wnested-externs -pedantic -fno-common
CPPFLAGS= -I. -DSHAREDIR=\"$(SHAREDIR)\" -DVERSION=\"$(VERSION)\"
LDFLAGS= -g
LIBM= -lm
all: diction style diction.1
# 可执行文件diction依赖于文件diction.o sentence.o misc.o getopt.o getopt1.o
diction: diction.o sentence.o misc.o getopt.o getopt1.o
$(CC) -o $@ $(LDFLAGS) diction.o sentence.o misc.o \
getopt.o getopt1.o $(LIBS)
style: style.o sentence.o misc.o getopt.o getopt1.o
$(CC) -o $@ $(LDFLAGS) style.o sentence.o misc.o \
getopt.o getopt1.o $(LIBM) $(LIBS)
diction.1: diction.1.in Makefile
sed -e s+/usr/share+$(SHAREDIR)+ diction.1.in >$@
install: all
$(INSTALL) -m 755 -d $(BINDIR)
$(INSTALL_PROGRAM) -s diction $(BINDIR)/diction
$(INSTALL_PROGRAM) -s style $(BINDIR)/style
$(INSTALL) -m 755 -d $(SHAREDIR)/diction
$(INSTALL_DATA) de $(SHAREDIR)/diction/de
$(INSTALL_DATA) en $(SHAREDIR)/diction/en
(cd $(SHAREDIR)/diction; rm -f C; ln en C)
$(INSTALL) -m 755 -d $(MANDIR)/man1
$(INSTALL_DATA) diction.1 $(MANDIR)/man1/diction.1
$(INSTALL_DATA) style.1 $(MANDIR)/man1/style.1
install.msg:
gencat -o ${prefix}/share/locale/en_US/LC_MESSAGES/diction.cat diction-en.msg sentence-en.msg
gencat -o ${prefix}/share/locale/en_US/LC_MESSAGES/style.cat style-en.msg sentence-en.msg
#{{{script}}}#{{{ clean
clean:
rm -f *.out core *.o diction.1
#}}}
#{{{ clobber
clobber: clean
rm -f diction style config.cache config.h config.log config.status Makefile
#}}}
#{{{ tar
tar: clobber
(b=`pwd`; b=`basename $$b`; cd ..; tar zcvf $$b.tar.gz $$b/COPYING $$b/INSTALL $$b/Makefile.in $$b/README $$b/configure $$b/install-sh $$b/de $$b/en $$b/[a-z]*.*)
#}}}