如何连接两个字符串以构建完整路径


93

我正在尝试编写bash脚本。在此脚本中,我希望用户输入目录的路径。然后,我想在此字符串的末尾附加一些字符串,并为某些子目录建立路径。例如,假设用户输入如下字符串:

/home/user1/MyFolder

现在,我想在此目录中创建2个子目录,并在其中复制一些文件。

/home/user1/MyFolder/subFold1
/home/user1/MyFolder/subFold2

我怎样才能做到这一点?


1
你都尝试了些什么?另外,您的问题之一是有关从用户那里获取输入的信息,另一部分是有关构建路径的问题?还是只是路径?
Levon 2012年

Answers:


133

POSIX标准要求在文件名中将多个/视为单个/。因此 //dir///subdir////file与相同/dir/subdir/file

因此,将两个字符串连接起来以构建完整路径很简单:

full_path="$part1/$part2"

11
$ part1是否可以为空字符串。
Tuure Laurinolli

1
@TuureLaurinolli我不明白你来自哪里。上述串联仍将导致有效路径。该路径可能不存在,但仍然有效。例如。"" + "/" + "Documents""/Documents"
沙丘

17
如果零件本身是相对路径,而part1可能为空,则结果可能从相对路径变为绝对路径。
Tuure Laurinolli

2
@TuureLaurinolli然后您可以简单地添加./到前面。但是也许用户想要连接绝对路径。否则,它们可以简单地添加./到前面以强制路径相对。另请注意,"$path1/./$path2"与相同"$path1/$path2"
yyny

41
#!/bin/bash

read -p "Enter a directory: " BASEPATH

SUBFOLD1=${BASEPATH%%/}/subFold1
SUBFOLD2=${BASEPATH%%/}/subFold2

echo "I will create $SUBFOLD1 and $SUBFOLD2"

# mkdir -p $SUBFOLD1
# mkdir -p $SUBFOLD2

如果您想使用readline来获取完成信息和所有信息,请-e在的调用中添加read

read -e -p "Enter a directory: " BASEPATH

1
不幸的是,当BASEPATH为空时,这不起作用。我需要的是这样的东西,它仅在斜杠尚未结束且不为空时才添加/。因此,当它以合​​法的文件名字符结尾时。
卡洛·伍德

16

不会简单地串联路径的一部分来完成您想要的?

$ base="/home/user1/MyFolder/"
$ subdir="subFold1"
$ new_path=$base$subdir
$ echo $new_path
/home/user1/MyFolder/subFold1

然后,您可以根据需要创建文件夹/目录。

一种约定是用/(例如/home/)结束目录路径,因为以/开头的路径可能与根目录混淆。如果//在路径中使用双斜杠(),则它仍然是正确的。但是,如果在任何一个变量上都没有使用斜杠,那将是不正确的(例如/home/user1/MyFoldersubFold1)。


3
为什么收到此消息:Myscript.sh:第4行:/ home / user1 / MyFolder / subFold1:是目录
Hakim

2
您在路径中缺少/。目标是内联的,/home/user1/MyFolder/subFold1 所以您需要内联new_path=$base/$subdir。但是,如果给定的路径包含结尾的“ /”,您该怎么办?
Thrasi

1
@Thrasi只需将结尾的'/'添加到subdir变量中,或者newpath=$base/$subdir/您可以在命令行上直接使用它
user12345

3
@ user12345,是的...仍然使上述解决方案不正确。
Thrasi

5

以下脚本用相对路径(SUBDIR)覆盖多个(相对/绝对)路径(BASEPATH):

shopt -s extglob
SUBDIR="subdir"
for BASEPATH in '' / base base/ base// /base /base/ /base//; do
  echo "BASEPATH = \"$BASEPATH\" --> ${BASEPATH%%+(/)}${BASEPATH:+/}$SUBDIR"
done

输出为:

BASEPATH = "" --> subdir
BASEPATH = "/" --> /subdir
BASEPATH = "base" --> base/subdir
BASEPATH = "base/" --> base/subdir
BASEPATH = "base//" --> base/subdir
BASEPATH = "/base" --> /base/subdir
BASEPATH = "/base/" --> /base/subdir
BASEPATH = "/base//" --> /base/subdir

shopt -s extglob仅需要允许基本路径,结束对多个斜线(这可能是无义)。如果没有扩展的问题,您可以使用:

echo ${BASEPATH%%/}${BASEPATH:+/}$SUBDIR

这将导致较不整洁但仍能正常工作:

BASEPATH = "" --> subdir
BASEPATH = "/" --> /subdir
BASEPATH = "base" --> base/subdir
BASEPATH = "base/" --> base/subdir
BASEPATH = "base//" --> base//subdir
BASEPATH = "/base" --> /base/subdir
BASEPATH = "/base/" --> /base/subdir
BASEPATH = "/base//" --> /base//subdir

1

我正在处理我的shell脚本,该脚本需要像您一样做一些路径连接工作。

问题是,两条路径都一样

/data/foo/bar

/data/foo/bar/ 

是有效的。

如果我想将文件追加到此路径,例如

/data/foo/bar/myfile

Shell中没有本地方法(如python中的os.path.join())来处理这种情况。

但是我确实找到了一个窍门

例如,基本路径存储在shell变量中

BASE=~/mydir

您要加入的最后一个文件名是

FILE=myfile

然后您可以像这样分配新路径

NEW_PATH=$(realpath ${BASE})/FILE

然后你会得到

$ echo $NEW_PATH

/path/to/your/home/mydir/myfile

原因很简单,“ realpath”命令将始终为您修剪终止斜杠


0
#!/usr/bin/env bash

mvFiles() {
    local -a files=( file1 file2 ... ) \
             subDirs=( subDir1 subDir2 ) \
             subDirs=( "${subDirs[@]/#/$baseDir/}" )

    mkdir -p "${subDirs[@]}" || return 1

    local x
    for x in "${subDirs[@]}"; do
        cp "${files[@]}" "$x"
    done
}



main() {
    local baseDir
    [[ -t 1 ]] && echo 'Enter a path:'
    read -re baseDir
    mvFiles "$baseDir"
}

main "$@"

0

这应该适用于空目录(您可能需要检查第二个字符串是否以该字符串开头/,应将其视为绝对路径?):

#!/bin/bash

join_path() {
    echo "${1:+$1/}$2" | sed 's#//#/#g'
}

join_path "" a.bin
join_path "/data" a.bin
join_path "/data/" a.bin

输出:

a.bin
/data/a.bin
/data/a.bin

参考:Shell参数扩展

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.