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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/11226322/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-06 07:05:25  来源:igfitidea点击:

How to concatenate two strings to build a complete path

linuxbash

提问by Hakim

I am trying to write a bash script. In this script I want user to enter a path of a directory. Then I want to append some strings at the end of this string and build a path to some subdirectories. For example assume user enters an string like this:

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

/home/user1/MyFolder

Now I want to create 2 subdirectories in this directory and copy some files there.

现在我想在这个目录中创建 2 个子目录并在那里复制一些文件。

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

How can I do this?

我怎样才能做到这一点?

回答by Levon

Won't simply concatenating the part of your path accomplish what you want?

简单地连接路径的一部分不会完成你想要的吗?

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

You can then create the folders/directories as needed.

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

One convention is to end directory paths with /(e.g. /home/) because paths starting with a / could be confused with the root directory. If a double slash (//) is used in a path, it is also still correct. But, if no slash is used on either variable, it would be incorrect (e.g. /home/user1/MyFoldersubFold1).

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

回答by Sean Bright

#!/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

And if you want to use readline so you get completion and all that, add a -eto the call to read:

如果您想使用 readline 来完成所有这些,请-e在调用中添加一个read

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

回答by ormaaj

#!/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 "$@"

回答by Dunes

The POSIX standard mandates that multiple /are treated as a single /in a file name. Thus //dir///subdir////fileis the same as /dir/subdir/file.

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

As such concatenating a two strings to build a complete path is a simple as:

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

full_path="$part1/$part2"

回答by Carlo Wood

The following script catenates several (relative/absolute) paths (BASEPATH) with a relative path (SUBDIR):

以下脚本将多个(相对/绝对)路径 (BASEPATH) 与相对路径 (SUBDIR) 联系起来:

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

The output of which is:

其输出为:

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

The shopt -s extglobis only necessary to allow BASEPATH to end on multiple slashes (which is probably nonsense). Without extended globing you can just use:

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

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

which would result in the less neat but still working:

这将导致不那么整洁但仍然有效:

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

回答by tsl0922

This should works for empty dir (You may need to check if the second string starts with /which should be treat as an absolute path?):

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

#!/bin/bash

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

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

Output:

输出:

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

Reference: Shell Parameter Expansion

参考:Shell 参数扩展

回答by u11265208

I was working around with my shell script which need to do some path joining stuff like you do.

我正在处理我的 shell 脚本,它需要像你一样做一些路径连接。

The thing is, both path like

问题是,两条路径都像

/data/foo/bar

/data/foo/bar/ 

are valid.

是有效的。

If I want to append a file to this path like

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

/data/foo/bar/myfile

there was no native method (like os.path.join() in python) in shell to handle such situation.

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

But I did found a trick

但我确实找到了一个技巧

For example , the base path was store in a shell variable

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

BASE=~/mydir

and the last file name you wanna join was

你想加入的最后一个文件名是

FILE=myfile

Then you can assign your new path like this

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

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

and then you`ll get

然后你会得到

$ echo $NEW_PATH

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

the reason is quiet simple, the "realpath" command would always trim the terminating slash for you if necessary

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