J'essaie d'écrire un script bash. Dans ce script, je veux que l'utilisateur entre le chemin d'un répertoire. Ensuite, je souhaite ajouter des chaînes à la fin de cette chaîne et créer un chemin vers certains sous-répertoires . Par exemple, supposons que l'utilisateur entre une chaîne comme celle-ci:
/home/user1/MyFolder
Maintenant, je veux créer 2 sous-répertoires dans ce répertoire et y copier des fichiers.
/home/user1/MyFolder/subFold1
/home/user1/MyFolder/subFold2
Comment puis-je faire ceci?
La norme POSIX exige que plusieurs /
soient traités comme un seul /
dans un nom de fichier. Ainsi, //dir///subdir////file
est identique à /dir/subdir/file
.
En tant que tel, concaténer deux chaînes pour créer un chemin complet est simple:
full_path="$part1/$part2"
#!/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
Et si vous voulez utiliser readline afin d’être complet et tout le reste, ajoutez un -e
à l’appel de read
:
read -e -p "Enter a directory: " BASEPATH
Ne concaténez-vous pas simplement la partie de votre chemin accomplissant ce que vous voulez?
$ base="/home/user1/MyFolder"
$ subdir="subFold1"
$ new_path=$base$subdir
$ echo $new_path
/home/user1/MyFoldersubFold1
vous pouvez ensuite créer les dossiers/répertoires selon vos besoins.
Le script suivant identifie plusieurs chemins (relatifs/absolus) (BASEPATH) avec un chemin relatif (SUBDIR):
shopt -s extglob
SUBDIR="subdir"
for BASEPATH in '' / base base/ base// /base /base/ /base//; do
echo "BASEPATH = \"$BASEPATH\" --> ${BASEPATH%%+(/)}${BASEPATH:+/}$SUBDIR"
done
Le résultat est:
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
Le shopt -s extglob
est uniquement nécessaire pour permettre à BASEPATH de se terminer sur plusieurs barres obliques (ce qui est probablement absurde). Sans globing étendu, vous pouvez simplement utiliser:
echo ${BASEPATH%%/}${BASEPATH:+/}$SUBDIR
ce qui rendrait les moins soignés mais fonctionnant toujours:
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
#!/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 "$@"
Je travaillais avec mon script Shell qui doit créer un chemin pour rejoindre des choses comme vous le faites.
La chose est, les deux chemin comme
/data/foo/bar
/data/foo/bar/
sont valides.
Si je veux ajouter un fichier à ce chemin comme
/data/foo/bar/myfile
shell ne disposait d'aucune méthode native (comme os.path.join () en python) pour gérer cette situation.
Mais j'ai trouvé un truc
Par exemple, le chemin de base était stocké dans une variable Shell
BASE=~/mydir
et le dernier nom de fichier que vous voulez rejoindre était
FILE=myfile
Ensuite, vous pouvez assigner votre nouveau chemin comme ceci
NEW_PATH=$(realpath ${BASE})/FILE
et alors vous aurez
$ echo $NEW_PATH
/path/to/your/home/mydir/myfile
la raison en est simple, la commande "realpath" réduira toujours la barre oblique pour vous si nécessaire
Cela devrait fonctionner pour un répertoire vide (vous devrez peut-être vérifier si la deuxième chaîne commence par /
qui devrait être considéré comme un chemin absolu?):
#!/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
Sortie:
a.bin
/data/a.bin
/data/a.bin
Référence: Shell Parameter Expansion