【问题标题】:Bash script to change parent shell directory [duplicate]用于更改父 shell 目录的 Bash 脚本 [重复]
【发布时间】:2012-11-25 01:05:09
【问题描述】:

我要做什么

我创建了一个 shell 脚本,并将其添加到我的 $PATH 中,它将下载并为新的 Laravel 项目设置所有内容。我希望通过将终端目录更改为新项目文件夹来结束脚本。

据我目前了解,它只是更改脚本实际运行的子 shell 的目录。我似乎无法弄清楚如何做到这一点。任何帮助表示赞赏。谢谢!

#! /usr/bin/env bash

echo -e '\033[1;30m=========================================='

## check for a directory
if test -z "$1"; then
  echo -e ' \033[0;31m✖ Please provide a directory name'
  exit
fi

## check if directory already exist
if [ ! -d $1 ]; then
  mkdir $1
else
  echo -e ' \033[0;31m✖ The '"$1"' directory already exists'
  exit
fi

# move to directory
cd $1

## Download Laravel
echo -e ' \033[0;32m+ \033[0mDownloading Laravel...'
curl -s -L https://github.com/laravel/laravel/zipball/master > laravel.zip

## Unzip, move, and clean up Laravel
echo -e ' \033[0;32m+ \033[0mUnzipping and cleaning up files...'
unzip -q laravel.zip
rm laravel.zip
cd *-laravel-*
mv * ..
cd ..
rm -R *-laravel-*

## Make the /storage directory writable
echo -e ' \033[0;32m+ \033[0mMaking /storage directory writable...'
chmod -R o+w storage

## Download and install the Generators
echo -e ' \033[0;32m+ \033[0mInstalling Generators...'
curl -s -L https://raw.github.com/JeffreyWay/Laravel-Generator/master/generate.php > application/tasks/generate.php

## Update the application key
echo -e ' \033[0;32m+ \033[0mUpdating Application Key...'
MD5=`date +”%N” | md5`
sed -ie 's/YourSecretKeyGoesHere!/'"$MD5"'/' application/config/application.php
rm application/config/application.phpe

## Create .gitignore and initial git if -git is passed
if [ "$2" == "-git" ]; then
  echo -e ' \033[0;32m+ \033[0mInitiating git...'
  touch .gitignore
  curl -s -L https://raw.github.com/gist/4223565/be9f8e85f74a92c95e615ad1649c8d773e908036/.gitignore > .gitignore

  # Create a local git repo
  git init --quiet
  git add * .gitignore
  git commit -m 'Initial commit.' --quiet
fi

echo -e '\033[1;30m=========================================='
echo -e ' \033[0;32m✔ Laravel Setup Complete\033[0m'

## Change parent shell directory to new directory
## Currently it's only changing in the sub shell
filepath=`pwd`
cd "$filepath"

【问题讨论】:

    标签: bash shell unix cd


    【解决方案1】:

    这是不可能的。使用exec 在适当的目录中打开一个新的shell,替换脚本解释器。

    exec bash
    

    【讨论】:

    • 稍微解释一下exec 会改进这个答案。
    • 我看不出exec 与这里有什么关系,您仍然处于原始外壳的子外壳中。但是,我认为这是非常违反直觉的——我通常希望脚本终止,而不是让我进入另一个 shell。重复使用这个脚本会开始积累子shell ...
    • @cebewee,我认为@ignacio-vazquez-abrams 的意思是你应该exec bash the_script,它将用执行脚本替换原来的shell;但是,除其他外,这也会导致 shell 在脚本完成后立即退出。如果没有解释,这个答案是非常错误的。
    • 这是一个有用的答案,尽管并不理想。我敢肯定,对于一些绝望的灵魂来说,这已经足够了。
    【解决方案2】:

    从技术上讲,您可以 source 您的脚本在您的父 shell 中运行它,而不是生成一个子 shell 来运行它。这样,您对当前 shell 所做的任何更改(包括更改目录)都会持续存在。

    source /path/to/my/script/script
    

    或

    . /path/to/my/script/script
    

    但采购有其自身的危险,请谨慎使用。

    (外围相关:如何use scripts to change directories)

    【讨论】:

    • 出于某种原因,这似乎对我不起作用。我已经尝试了两种方法。获取脚本后,如何调用它?
    • @michaelespinosa 采购脚本正在调用它。如果你想把它变成一个可调用的命令,请将你的整个脚本包装在一个函数中(例如,foo() {...script contents...} 然后将其作为源代码;在命令提示符下调用该函数以执行其中的指令。
    • 好的,在这种情况下,当我获取文件时,我的 Mac 上的终端崩溃了。有趣...
    【解决方案3】:

    我想一种可能性是确保脚本的唯一输出是您想要结束的路径名,然后执行:

    cd `/path/to/my/script`
    

    您的脚本无法直接影响其父 shell 的环境(包括当前目录),但这会要求父 shell 本身根据脚本的输出更改目录...

    【讨论】:

      【解决方案4】:

      子进程(包括 shell)不能改变父进程的当前目录。典型的解决方案是在父 shell 中使用 eval。在您希望由父 shell 运行的 shell 脚本 echo 命令中:

      echo "cd $filepath"
      

      在父 shell 中,你可以用 eval 踢掉 shell 脚本:

      eval `sh foo.sh`
      

      请注意,所有标准输出都将作为 shell 命令执行。消息应该输出到标准错误:

      echo "Some messages" >&2
      command ... >&2
      

      【讨论】:

        【解决方案5】:

        使用 shell 函数来前端你的脚本

        setup () {
          # first, call your big script.
          # (It could be open-coded here but that might be a bit ugly.)
        
          # then finally...
        
          cd someplace
        }
        

        将shell函数放在一个shell启动文件中。

        【讨论】:

        • 这实际上对我有用,谢谢!当脚本因为重复终端窗口崩溃而调用“退出”时出现问题。
        • 对于其他阅读本文的人来说,shell 函数可以像脚本一样传递参数。在函数内部,$*, $@, 和 $1, $2 ... 都引用传递给函数的参数,即setup arg1 arg2。
        • 我可以通过将脚本包装在 if 语句中而不是调用 exit 来修复崩溃。谢谢@DigitalRoss
        猜你喜欢
        • 2017-04-09
        • 1970-01-01
        • 2017-04-01
        • 1970-01-01
        • 1970-01-01
        • 2014-04-12
        • 1970-01-01
        • 2021-02-08
        • 2020-02-11
        相关资源
        最近更新 更多