Linux复制目录结构并为具有不同扩展名的现有文件创建符号链接

时间:2018-04-17 23:15:22

标签: bash

我有一个类似于以下

的大型目录结构
/home/user/abc/src1
                   /file_a.xxx
                   /file_b.xxx
/home/user/abc/src2
                   /file_a.xxx
                   /file_b.xxx

它包含多个srcX文件夹并且包含许多文件,大多数文件的扩展名为.xxx。这些是我感兴趣的。

我想在/ tmp中创建一个相同的目录结构。这部分我已经能够通过rsync完成

rsync -av -f"+ */" -f"- *" /home/user/abc/ /tmp/xyz/

下一步是我无法弄清楚的。我需要/ tmp / xyz中的目录结构,以使用不同的文件扩展名(.zzz)为/ home / user / abc中的所有文件添加符号链接。目录结构如下所示:

/tmp/xyz/src1
             /file_a.zzz -> /home/user/abc/src1/file_a.xxx
             /file_b.zzz -> /home/user/abc/src1/file_b.xxx
/tmp/xyz/src2
             /file_a.zzz -> /home/user/abc/src2/file_a.xxx
             /file_b.zzz -> /home/user/abc/src2/file_b.xxx

我知道我可以复制数据并进行批量重命名。这不是一个可以接受的解决方案。

如何递归为/ home / user / abc中的所有.xxx文件创建符号链接,并将它们链接到扩展名为.zzz的/ tmp / xyz。

find + exec看起来像我想要的但是我不能把2和2放在一起。

3 个答案:

答案 0 :(得分:1)

这可行吗

cd /tmp/xyz/src1
find /home/user/abc/src1/ -type f -print0 | xargs -r0 -I '{}' ln -s '{}' $(basename '{}' .xxx).zzz 

答案 1 :(得分:0)

导航到/tmp/xyz/,然后运行以下脚本:

#!/usr/bin/env bash

# First make src* folders in present directory:                                          
mkdir -p $(find ~/user/abc/src* -type d -name "src*" | rev | cut -d"/" -f1 | rev)

# Then make symbolic links:
while read -r -d' ' file; do                                     
    ln -s  ${file} $(echo ${file} | rev | cut -d/ -f-2 | rev  | sed 's/\.xxx/\.zzz/')            
done <<< $(echo "$(find ~/user/abc/src* -type f -name '*.xxx') dummy")   

答案 2 :(得分:0)

感谢所有输入。基于我看到的想法,我能够提出一个符合我需求的脚本。

#!/bin/bash

GLOBAL_SRC_DIR="/home/usr/abc"
GLOBAL_DEST_DIR="/tmp/xyz"

create_symlinks ()
{
    local SRC_DIR="${1}"
    local DEST_DIR="${2}"

    # read in our file, use null terminator
    while IFS= read -r -d $'\0' file; do

            # If file ends with .xxx or .yyy
            if [[ ${file} =~ .*\.(xxx|yyy) ]] ; then
                    basePath="$(dirname ${file})"
                    fileName="$(basename ${file})"
                    completeSourcePath="${basePath}/${fileName}"
                    #echo "${completeSourcePath}"

                    # strip off preceding text
                    partialDestPath=$(echo ${basePath} | sed -r "s|^${SRC_DIR}||" )
                    fullDestPath="${DEST_DIR}/${partialDestPath}"

                    # rename file from .xxx to .zzz. don't rename just link .yyy
                    cppFileName=$(echo ${fileName} | sed -r "s|\.xxx$|\.zzz|" )
                    completeDestinationPath="${fullDestPath}/${cppFileName}"

                    $(ln -s ${completeSourcePath} ${completeDestinationPath})
            fi
    done < <(find ${SRC_DIR} -type f -print0)
}

main ()
{
    create_symlinks ${GLOBAL_SRC_DIR} ${GLOBAL_DEST_DIR}
}

main