Bash脚本将目录结构从源目录复制到目标目录

时间:2016-04-13 20:43:38

标签: linux bash shell scripting

我是Bash scritping的新手并且想要练习,我正在尝试编写一个包含源目录和目标目录的脚本。该脚本将搜索源目录并将其子目录结构复制到目标目录中(任何文件都将被忽略,只是目录本身将被复制)。源目录可以具有任意深度的任意数量的子目录。实现这一目标的最佳方法是什么?我已经开始尝试编写一个递归函数,其中,如果找到一个目录,该函数将被递归地调用到该目录中。但是,由于我缺乏脚本编写经验,我一直很难过。

这是我到目前为止所做的:

#! /bin/bash

if [ ! $# -eq 2 ]; then 
    echo "ERROR: Script needs 2 arguments: $0 source/directory/ target/directory/"
    exit
fi

SOURCE_DIR=$1
TARGET_DIR=$2

function searchForDirectory {
    for FILE in ls $SOURCE_DIR/*; do #should be 'ls *current_directory*'
        if [ -d $FILE ]; then
            searchForDirectory #call function recursively onto $FILE
            #Do stuff here to create copy of this directory in target dir
        fi
    done
}

if [ ! -d $SOURCE_DIR ]; then 
    echo "ERROR: Source directory does not exist"
    exit
else
    searchForDirectory
fi

我知道这只是一个骨架功能,还需要投入更多的工作,但我只是在寻找指导,看看这是否是正确的方法来解决这个问题。进一步,如果是这样,我的下一步是什么?如何将目录传递给我的函数?

编辑:感谢Ivan的帮助,这是我的解决方案     #! /斌/庆典

if [ ! $# -eq 2 ]; then 
    echo -e "\nERROR: Script needs 2 arguments:\n$0 source/directory/ target/directory/\n"
    exit
fi

function recursiveDuplication {
    for file in `ls $1`; do
        if [ -d $1/$file ] && [ ! -d $2/$file ]; then
            mkdir $2/$file
            recursiveDuplication $1/$file $2/$file
        elif [[ $1/$file == *.png ]]; then
            convert $1/$file $2/$file
        fi
    done
}

if [ ! -d $1 ]; then 
    echo -e "\nERROR: $1 does not exist\n"
    exit
elif [ -d $2 ] && [ ! -w $2 ]; then
    echo -e "\nERROR: You do not have permission to write to $2\n"
    exit
elif [ ! -d $2 ]; then
    echo -e "\nSUCCESS: $2 has been created"
    mkdir $2
fi

recursiveDuplication $1 $2

此解决方案存在两个问题:

  1. 正如Rany Albeg Wein在下面解释的那样,使用' ls'不是一个好的解决方案 - 我已经看到了目录/ * .png名称中有空格的原因。

  2. 我还尝试将任何* .png文件从源复制到目标,并将其转换为目标中的* .jpg图像。我怎样才能做到这一点?我正在尝试使用ImageMagick的convert image.png image.jpg命令,但在image.png被称为$file时却不知道如何执行此操作?

3 个答案:

答案 0 :(得分:0)

你可以简化很多

$ find a -type d | xargs -I d mkdir -p copy/d

将目录a中的树结构复制到copy

下的新目录
$ tree a
a
|-- b
|   |-- c
|   |   `-- file4
|   |-- d
|   |   `-- file4
|   `-- file3
`-- file2

3 directories, 4 files


$ tree copy
copy
`-- a
    `-- b
        |-- c
        `-- d

4 directories, 0 files

答案 1 :(得分:0)

此解决方案已使用包含特殊字符的目录名称,目录树中的循环和损坏的符号链接进行测试。

有一个明智的解决方案:

( cd source/ ; find . -depth -type d -printf "%p\0" | xargs -0 -I xxx mkdir -p ../destination/xxx )

还有第二种解决方案使用gnu cpio

( cd source/ ; find . -depth -type d -printf "%p\0" | cpio --null -pd ../destination )

测试:

$ mkdir -p source/a/ba/c/d/e
$ mkdir -p source/a/bb/c/d/e
$ mkdir -p source/a/b/ca/d/e
$ ln -s source/broken/link source/a/ba/c/d/e/broken
$ (cd source/a/ba && ln -s ../../a  tree-loop)
$ mkdir -p source/z/"$(printf "\1\2\3\4\5\6\7\10\11\12\13\14\15\16\17\20\21\22\23\24\25\26\27\30\31\32\33\34\35\36\37\40\41\42\43\44\45\46\47\72\73\74\75\76\77\100\133\134\135\1336\137\140\173\174\175\176\177dir")" 
$ touch source/a/b/"$(printf "\1\2\3\4\5\6\7\10\11\12\13\14\15\16\17\20\21\22\23\24\25\26\27\30\31\32\33\34\35\36\37\40\41\42\43\44\45\46\47\72\73\74\75\76\77\100\133\134\135\1336\137\140\173\174\175\176\177file")"
$ ls 
source
$ find source -depth
source/z/??????????????????????????????? !"#$%&':;<=>?@[\][6_`{|}~?dir
source/z
source/a/ba/tree-loop
source/a/ba/c/d/e/broken
source/a/ba/c/d/e
source/a/ba/c/d
source/a/ba/c
source/a/ba
source/a/b/ca/d/e
source/a/b/ca/d
source/a/b/ca
source/a/b/??????????????????????????????? !"#$%&':;<=>?@[\][6_`{|}~?file
source/a/b
source/a/bb/c/d/e
source/a/bb/c/d
source/a/bb/c
source/a/bb
source/a
source

$ ( cd source/ ; find . -depth -type d -printf "%p\0" | xargs -0 -I xxx mkdir -p ../destination/xxx )
$ find destination/ -depth 
destination/z/??????????????????????????????? !"#$%&':;<=>?@[\][6_`{|}~?dir
destination/z
destination/a/ba/c/d/e
destination/a/ba/c/d
destination/a/ba/c
destination/a/ba
destination/a/b/ca/d/e
destination/a/b/ca/d
destination/a/b/ca
destination/a/b
destination/a/bb/c/d/e
destination/a/bb/c/d
destination/a/bb/c
destination/a/bb
destination/a
destination/

gnu cpio测试:

$ rm -rf destination
$ ( cd source/ ; find . -depth -type d -printf "%p\0" | cpio --null -pd ../destination )
0 blocks

$ find destination -depth
destination/z/??????????????????????????????? !"#$%&':;<=>?@[\][6_`{|}~?dir
destination/z
destination/a/ba/c/d/e
destination/a/ba/c/d
destination/a/ba/c
destination/a/ba
destination/a/b/ca/d/e
destination/a/b/ca/d
destination/a/b/ca
destination/a/b
destination/a/bb/c/d/e
destination/a/bb/c/d
destination/a/bb/c
destination/a/bb
destination/a
destination

答案 2 :(得分:-2)

$challenge = $_REQUEST['hub_challenge'];
$verify_token = $_REQUEST['hub_verify_token'];

if ($verify_token === 'MY_VERIFICATION_TOKEN') {
  echo $challenge;
}

$input = json_decode(file_get_contents('php://input'), true);

$sender = $input['entry'][0]['messaging'][0]['sender']['id'];
$message = $input['entry'][0]['messaging'][0]['message']['text'];


//API Url
$url = 'https://graph.facebook.com/v2.6/me/messages?access_token=<my-token>';

//Initiate cURL.
$ch = curl_init($url);

//The JSON data.
$jsonData = '{
    "recipient":{
        "id":"'.$sender.'"
    }, 
    "message":{
        "text":"Hey Lee!"
    }
}';

//Encode the array into JSON.
$jsonDataEncoded = $jsonData;

//Tell cURL that we want to send a POST request.
curl_setopt($ch, CURLOPT_POST, 1);

//Attach our encoded JSON string to the POST fields.
curl_setopt($ch, CURLOPT_POSTFIELDS, $jsonDataEncoded);

//Set the content type to application/json
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: application/json'));

//Execute the request
$result = curl_exec($ch);