2つの文字列を連結して完全なパスを構築する方法


93

私はbashスクリプトを書こうとしています。このスクリプトでは、ユーザーにディレクトリのパスを入力してもらいます。次に、この文字列の最後にいくつかの文字列を追加して、いくつかのサブディレクトリへのパスを作成します。たとえば、ユーザーが次のような文字列を入力するとします。

/home/user1/MyFolder

次に、このディレクトリに2つのサブディレクトリを作成し、そこにいくつかのファイルをコピーします。

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

これどうやってするの?


1
これまでに何を試しましたか?また、ユーザーからの入力の取得に関する質問の一部と、パスの構築に関する他の部分はありますか?または単に道?
Levon

回答:


133

POSIX標準では、ファイル名で/は複数が単一として扱われることが義務付けられて/います。したがって //dir///subdir////file、と同じ/dir/subdir/fileです。

したがって、2つの文字列を連結して完全なパスを構築するのは、次のように簡単です。

full_path="$part1/$part2"

11
$ part1が空の文字列である場合を除いて。
Tuure Laurinolli 2017年

1
@TuureLaurinolliどこから来たのかわかりません。上記の連結でも、有効なパスになります。パスは存在しない可能性がありますが、それでも有効です。例えば。"" + "/" + "Documents"与え"/Documents"ます。
砂丘

17
パーツ自体が相対パスで、part1が空の場合、結果は相対パスから絶対パスに変わる可能性があります。
Tuure Laurinolli 2017年

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への呼び出しにa を追加します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

その後、必要に応じてフォルダ/ディレクトリを作成できます。

/で始まるパスはルートディレクトリと混同される可能性があるため、1つの規則は/(たとえば/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

次のスクリプトは、いくつかの(相対/絶対)パス(BASEPATH)を相対パス(SUBDIR)と連結します。

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は、BASEPATHが複数のスラッシュで終了できるようにするためにのみ必要です(これはおそらくナンセンスです)。拡張されたグロビングなしであなたはただ使うことができます:

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

私はあなたと同じようにいくつかのパスに参加するものを実行する必要がある私のシェルスクリプトを回避していた。

事は、両方のパスのようです

/data/foo/bar

/data/foo/bar/ 

有効です。

このパスにファイルを追加したい場合は

/data/foo/bar/myfile

そのような状況を処理するためのネイティブのメソッド(Pythonのos.path.join()など)はシェルにはありませんでした。

しかし、私はトリックを見つけました

たとえば、基本パスはシェル変数に格納されていました

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

これは空のディレクトリで機能するはずです(2番目の文字列が/絶対パスとして扱う必要があるかどうかを確認する必要がありますか?):

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

リファレンス:シェルパラメータの展開

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.