【问题标题】:Automatically create symlinks with lowercase names from uppercase directories从大写目录自动创建带有小写名称的符号链接
【发布时间】:2013-06-18 09:03:37
【问题描述】:

感谢您考虑提供帮助。

我正在尝试创建一个简单的 shell 脚本,该脚本运行后将查看文件夹中通常为大写形式的所有目录,并以小写形式创建指向该目录的符号链接。然后我将定期执行此脚本,因为新文件夹被添加到目录中以创建指向新文件夹的附加符号链接。该脚本必须知道已经为其创建了符号链接的其他文件夹,以免产生任何停止问题或错误。下面是我试图实现的可视化。

drwxr-xr-x 2 root root 4096 Jun 18 03:52 Holmes
drwxr-xr-x 2 root root 4096 Jun 18 03:52 Kingship
-rwxrwxrwx 1 root root   85 Jun 18 04:39 link.sh
drwxr-xr-x 2 root root 4096 Jun 18 03:52 Lost
drwxr-xr-x 2 root root 4096 Jun 18 03:52 Monkey
drwxr-xr-x 2 root root 4096 Jun 18 03:52 Space Ship
drwxr-xr-x 2 root root 4096 Jun 18 03:52 Test

lrwxrwxrwx  1 root root    6 Jun 18 04:49 holmes -> Holmes
drwxr-xr-x  2 root root 4096 Jun 18 03:52 Holmes
lrwxrwxrwx  1 root root    8 Jun 18 04:49 kingship -> Kingship
drwxr-xr-x  2 root root 4096 Jun 18 03:52 Kingship
-rwxrwxrwx  1 root root   85 Jun 18 04:39 link.sh
lrwxrwxrwx  1 root root    4 Jun 18 04:49 lost -> Lost
drwxr-xr-x  2 root root 4096 Jun 18 03:52 Lost
lrwxrwxrwx  1 root root    6 Jun 18 04:49 monkey -> Monkey
drwxr-xr-x  2 root root 4096 Jun 18 03:52 Monkey
lrwxrwxrwx  1 root root   10 Jun 18 04:49 space ship -> Space Ship
drwxr-xr-x  2 root root 4096 Jun 18 03:52 Space Ship
lrwxrwxrwx  1 root root    4 Jun 18 04:49 test -> Test
drwxr-xr-x  2 root root 4096 Jun 18 03:52 Test

显然,该脚本必须能够为稍后创建但还没有符号链接的文件夹创建新的符号链接。

我一直在修改其他两个帖子/答案的语法,除了重新创建单个答案的结果之外,我并没有真正得到任何地方。帖子在这里Using find on subdirectories and create symlinks to all filesBash script to automatically create symlinks to subdirectories in a tree

也许我正在用错误的方法解决我的问题。我实际上想要实现的是,这是一个 NAS 系统,它具有根据用户名自动创建的文件夹。然后这些文件夹会通过 samba home 共享自动共享。但是,除非创建小写文件夹,否则无法访问共享,因为这些文件夹最初是使用空格以及使用用户名的大小写结构创建的。用户名的结构与 unix 系统并不完全兼容,因为在 unix 系统上测试和测试是两个不同的东西。我研究了如何允许使用大写创建用户名,但是进行这些更改不会影响 samba 共享如何识别文件夹。

【问题讨论】:

    标签: bash active-directory sh symlink samba


    【解决方案1】:

    一步一步的方法:

    首先,在一个临时目录中,我正在创建一个像你这样的目录示例:

    $ mkdir Holmes Kingship Lost Monkey 'Space Ship' Test a_lower_case_one
    $ touch just_a_file One_with_UpperCase
    $ ln -s Holmes holmes
    $ ls -og
    total 28
    drwxr-xr-x 2 4096 Jun 18 11:54 a_lower_case_one
    lrwxrwxrwx 1    6 Jun 18 11:54 holmes -> Holmes
    drwxr-xr-x 2 4096 Jun 18 11:54 Holmes
    -rw-r--r-- 1    0 Jun 18 11:54 just_a_file
    drwxr-xr-x 2 4096 Jun 18 11:54 Kingship
    drwxr-xr-x 2 4096 Jun 18 11:54 Lost
    drwxr-xr-x 2 4096 Jun 18 11:54 Monkey
    -rw-r--r-- 1    0 Jun 18 11:54 One_with_UpperCase
    drwxr-xr-x 2 4096 Jun 18 11:54 Space Ship
    drwxr-xr-x 2 4096 Jun 18 11:54 Test
    

    现在,您将如何循环浏览您的目录?像这样:

    $ for i in */; do echo "$i"; done
    a_lower_case_one/
    holmes/
    Holmes/
    Kingship/
    Lost/
    Monkey/
    Space Ship/
    Test/
    

    如何在 bash 中将变量转换为小写?根据this section of the bash reference manual${i,,}的扩展将是$i小写的扩展:

    $ for i in */; do echo "$i -> ${i,,}"; done
    a_lower_case_one/ -> a_lower_case_one/
    holmes/ -> holmes/
    Holmes/ -> holmes/
    Kingship/ -> kingship/
    Lost/ -> lost/
    Monkey/ -> monkey/
    Space Ship/ -> space ship/
    Test/ -> test/
    

    现在我们只能考虑与其小写扩展不同的目录名:

    $ for i in */; do [[ $i = ${i,,} ]] && continue; echo "$i -> ${i,,}"; done
    Holmes/ -> holmes/
    Kingship/ -> kingship/
    Lost/ -> lost/
    Monkey/ -> monkey/
    Space Ship/ -> space ship/
    Test/ -> test/
    

    对于其中的每一个,我们将测试是否已经存在小写字母:

    $ for i in */; do [[ $i = ${i,,} ]] && continue; echo "$i -> ${i,,}"; if [[ -e ${i,,} ]]; then echo "    ${i,,} exists"; fi; done
    Holmes/ -> holmes/
        holmes/ exists
    Kingship/ -> kingship/
    Lost/ -> lost/
    Monkey/ -> monkey/
    Space Ship/ -> space ship/
    Test/ -> test/
    

    当小写字母已经存在时,我们将检查它是否是链接到大写字母的链接。如果是,一切都很好,否则我们将打印警告。因为有点大,我打算写成bash脚本:

    #!/bin/bash
    
    for i in */; do
        d=${i%/}
        dl=${d,,}
        [[ $d = $dl ]] && continue
        if [[ -e $dl ]]; then
            if [[ ! -L $dl ]]; then
                echo "    ERROR: $dl is not a link"
            elif [[ $(readlink -- "$dl") != $d ]]; then
                echo "    ERROR $dl exists and doesn't point to $d"
            fi
        else
            ln -sv -- "$d" "$dl"
        fi
    done
    

    我已经使用了我所知道的所有最佳实践,以便拥有一个健壮的脚本,确保文件名中的有趣符号(空格、连字符等)安全。

    注意。 必须从您要处理的目录中调用。如有必要,请在此脚本顶部使用 cd

    希望这会有所帮助!

    【讨论】:

    • 这是完美的解决方案,您使用的最佳实践可以让代码顺利执行,并在出现问题时提供适当的反馈。我已经在几个不同的环境中对此进行了测试,并且运行良好。此外,我从您的示例中学到了很多东西,并感谢您逐步进行布局。完美的答案,谢谢。
    猜你喜欢
    • 2012-03-19
    • 2011-01-16
    • 1970-01-01
    • 2011-11-14
    • 2018-04-24
    • 2012-12-01
    • 1970-01-01
    • 2019-07-01
    • 2023-03-14
    相关资源
    最近更新 更多