Obtenir un chemin absolu vers un dossier qui n'existe pas encore [bash]


1

Essayer de créer un script bash (sur mac) qui crée un dossier, puis exécute une série de scripts dans ce dossier. Je souhaite rappeler le chemin d'accès absolu au dossier et demander à l'utilisateur de confirmer avant de prendre des mesures.

Le script prend comme argument un chemin relatif, comment puis-je convertir un chemin absolu avant de créer le dossier?

!/bin/bash
if [[ $# -eq 0 ]] ; then
  echo 'Whoa! You dont want to do that! you need to tell me where to put it'
  exit 0
fi

ORG_DIR=$(pwd)
#here I want to get path before making directory, I've only figured out how to do after.
mkdir ../$1
cd ../$1
NEW_DIR=$(pwd)

echo "Running scripts in"
echo $NEW_DIR
read -p "Are you sure? (y/n) " -n 1 -r
if [[ ! $REPLY =~ ^[Yy]$ ]]
then
   # run a bunch of scripts
fi

Comment puis-je obtenir le chemin absolu de NEW_DIR avant de le créer?

Remarque: la plate-forme est OSX, je n'ai pas besoin de prendre en charge d'autres variantes de nix.

EDIT: Sam 29

Je me suis rendu compte que, dans un effort pour réduire la question aux détails essentiels, je réduisais trop mes excuses.

Ce script existe dans (par exemple saké)

/Documents/git/ProjectGenerator

J'ai l'intention que le script génère un projet (ou le chemin entré)

/Documents/git/NewProject

Il exécute une combinaison de scripts npm et copie des fichiers à partir de

/Documents/git/ProjectGenerator

Le reste du script fonctionne bien maintenant, mais j'ai récemment accidentellement appuyé sur Entrée avec le mauvais répertoire. Étant donné que ce script est destiné uniquement à mon usage (et non à sudo), j'essaie d'ajouter un contrôle d'intégrité, pas un contrôle de sécurité au début du script. Doit taper Y et entrer après avoir regardé le répertoire.

J'essaie d'obtenir un chemin absolu et ce que je reçois est

/Documents/git/ProjectGenerator/../NewProject

J'essaie de faire écho

/Documents/git/NewProject

avant de créer le répertoire. (parfois le chemin est beaucoup plus complexe)

En noeud nous avons path.resolve(path) En php ou c sa realpath(path)

Je n'arrive pas à trouver une commande équivalente dans osx bash, y en at-il une? ou dois-je analyser la chaîne?


Vous voudrez peut-être vérifier l'état de sortie de certaines de vos commandes. Ce qu'il se passe quand $1 est ../../../../../System ou foo bar?
user912264

Dans ce cas, ce n'est pas un script distribué, pour mon usage exclusif, donc pas de problèmes de confiance.
Philippe

Je souhaite que l'invite soit un contrôle de cohérence, pas un contrôle de sécurité.
Philippe

Réponses:


2

Vous souhaitez passer au répertoire précédent avec .. et cela pose des problèmes pour trouver le chemin absolu de votre nouveau répertoire (nommé $1 dans votre script, je l'appellerai $new_directory_name ici) ce sera ../$new_directory_name.

Avant de faire cd ou mkdir, J'utiliserais le basename commande pour afficher le répertoire d'origine ( $PWD le chemin absolu, puis ajouter $new_directory_name à cela, comme ceci:

echo $(dirname $PWD)/$new_directory_name

(ou remplacez le $(...) substitution de commandes avec les backticks `...` (ils sont parfois amusants sur stackexchange - voir la section Substitution de commandes de man bash

Je pense que vous pouvez simplement utiliser Parameter Expansion de bash (également dans man bash ) sur $PWD au lieu de basename comme ça:

 echo ${PWD%/*}/$new_directory_name

Exemples

$ new_directory_name=newdir
$ pwd
/tmp/testdir
$ echo ${PWD%/*}/$new_directory_name
/tmp/newdir
$ echo $(dirname $PWD)/$new_directory_name
/tmp/newdir

Comme pour les mentions user912264, vous pouvez vérifier si .. est un répertoire accessible en écriture (avec stat -c %a ou %A ), ou si vous êtes déjà en / puis cd .. ne va pas n'importe où nouveau, ou juste regarder pour les erreurs de mkdir, comme

mkdir ... || { echo mkdir ERROR exiting; exit; }

Je ne sais pas trop comment l'obtention du nom de base m'aide à transformer le chemin en absolu. $(pwd) donne déjà un chemin absolu vers le répertoire en cours. J'essaie d'éviter de créer un répertoire pour obtenir son chemin absolu.
Philippe

Avez-vous un exemple de répertoire dans lequel vous vous trouvez et un nouveau nom de répertoire que vous essayez de créer, en cas d'échec? Ah, attends, je vois un problème déroutant avec les noms de variables dans votre script, vous utilisez $NEW_DIR après l'avoir créé et qu'il a déjà un chemin absolu; mon $NEW_DIR fonctionnera avec un nom de dossier uniquement, pas de chemin (je modifierai ma réponse pour préciser, je le renommerai en $new_directory_name )
Xen2050

1

De ce commentaire sur le dépassement de pile https://stackoverflow.com/questions/284662/how-do-you-normalize-a-file-path-in-bash#comment81662652_284671

Je suis venu à la conclusion coreutils (que j'avais déjà installé) a le greadlink commande qui a la fonctionnalité dont j'ai besoin.

NEW_DIR=$(greadlink -f ../$1)

EDIT 1:

#!/bin/bash
if [[ $# -eq 0 ]] ; then
  #simple check to ensure enter was not accidently pressed without directory specified
  echo 'Whoa! You dont want to do that! you need to tell me where to put it';
  exit 0
fi

ORG_DIR=$(pwd)
#here I want to get path before making directory, I've only figured out how to do after.
NEW_DIR=$(greadlink -f ../$1)

echo "Running scripts in"
echo $NEW_DIR
read -p "Are you sure? (y/n) " -n 1 -r
if [[ $REPLY =~ ^[Yy]$ ]]
then

  cp -r $ORG_DIR/skeleton $NEW_DIR

  cd $NEW_DIR

  #init the project with default answers.
  yarn init -y

  #add dev scripts
  yarn add --dev webpack webpack-cli babel-loader @babel/preset-react @babel/core @babel/preset-env webpack-dev-server css-loader sass-loader node-sass style-loader file-loader url-loader redux-devtools eslint eslint-plugin-react babel-eslint

  #add production scripts
  yarn add react react-dom react-hot-loader react-redux redux redux-saga redux-socket.io socket.io

fi

Bien que cela réponde à ma question, je la laisse ouverte dans l'espoir d'une solution native (pour des raisons pédagogiques). Si quelqu'un en a une, j'accepte cette réponse.
Philippe

1
Pour votre information, greadlink ne semble pas être dans une installation standard de Debian / coreutils, mais readlink est, et semble prendre à peu près autant time courir comme dirname, tandis que l'expansion des paramètres de bash ( echo ${PWD%/*}/$new_directory_name ) n'enregistre rien avec time (0m0.000s), juste au cas où quelqu'un a l'intention d'exécuter les commandes BEAUCOUP
Xen2050

1
Intéressant, je ne savais pas que osx était si différent. Je crois que la source originale de coreutils est GNU ( brève histoire intéressante ), et les "grosses" distributions (ou bricolage) comme Debian créent leurs paquets à partir de là, allant jusqu'aux distributions dérivées. Je parie que la version osx vient de GNU aussi, mais je ne suis pas sûr. Quoi qu'il en soit, readlink fonctionne aussi, alors les votes positifs se multiplient ;-)
Xen2050

1
@ Xen2050 OSX lui-même est une branche d'Unix connue sous le nom de Darwin. Je pense qu'ils ont évolué vers la fin des années 90. Depuis lors, ils ont évolué dans différentes directions.
Philippe

1
Je me souviens avoir lu quelque chose de similaire quelque part, les choses deviennent confuses avec les «histoires de famille» du système d’exploitation, comme le Timeline de distribution Linux image . Je pense que BSD est également impliqué - a trouvé un Unix history-simple image avec macOS sous Wikipedia histoire macOS (suppose qu'ils appellent juste "macOS" maintenant)
Xen2050
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.