【问题标题】:Bash - CD into Untared directory with variable URLBash - 使用可变 URL 将 CD 放入 Untared 目录
【发布时间】:2012-07-14 12:55:33
【问题描述】:

情况就是这样。我有一个需要提取和设置的 URL 列表。它都是变量驱动的,但是在我提取之后,我不知道我的文件夹将被调用。如果我不知道它叫什么,我就不能 CD 进去。

$DL_DIR = /opt/
$URL = http://nginx.org/download/nginx-1.3.3.tar.gz
$FILE=${URL##*/}
$CONFIG = "-- core"

cd "$DL_DIR"
wget $URL
tar xzf $FILE
cd <HOW DO I GO INTO IT?>
./configure "$CONFIG"
make
make install
rm $FILE

如果这不能解释它,请说。我真的很想解决这个问题,但我很难解释它。

因为我希望它适用于任何一组 URL,这些 URL 可能有两种格式,如“.tar.gz”或一种格式“.zip”,并且文件名中可能有 .',如“Python2.3.4”或可能不是“Nginx”,这有点棘手。

【问题讨论】:

  • 顺便说一句,您的前四行在 bash 中不是有效的分配。左侧不应以美元符号为前缀,等号周围不允许有空格。更正示例:DLDIR=/opt/.

标签: regex bash shell unix


【解决方案1】:
extract_dir=$(tar -tf $FILE | cut -d/ -f1 | uniq)
cd $extract_dir

extract_dir=$(tar -tf $FILE | head -1 | cut -d/ -f1)
cd $extract_dir

ls > .dir_list_1    # save current directory listing as hidden file
tar xzf $FILE       # extract the $FILE
ls > .dir_list_2    # save the directory listing after extraction...
                    # ...as another hidden file
# diff two lists saved in hidden files, this will help you get the created dir
# grep '>' symbol, to get the inserted line
# use head to get the dir in case there are multiple lines (not necessary)
# use cut to remove the '>' and get the actual dir name, store in extract_dir
extract_dir=$(diff .dir_list_1 .dir_list_2 | grep '>' | head -1 | cut -d' ' -f2)
# remove temporary files 
rm .dir_list_*
cd $extract_dir

【讨论】:

  • 这就是棘手的地方。文件格式并不总是 tar,它可能是 .zip 或 .tar.gz
【解决方案2】:

如果您知道 $DL_DIR 中只有一个目录,那么您可以使用:

cd`ls -m1`

另一种方法是遍历目录的文件:

对于“$DL_DIR”中的文件名/* 做 回声$文件名 完毕;

您可以根据需要执行文件测试和其他检查。

【讨论】:

  • 好主意,但是这个目录里会有很多。我们可以根据时间来做吗?复制最新创建的文件夹的名称?不过,这似乎是一种不好的做法。
  • @JamesWillson:在这种情况下,您可以遍历 $DL_DIR 中的文件。请参阅我编辑的答案。
【解决方案3】:

这个怎么样:

rm -rf tmpdir
mkdir tmpdir && cd tmpdir || exit
wget "$URL" || exit 1
case "$(ls)" in
  *.tar.gz|*.tgz)
  tar xzf $(ls)
  ;;
  *.zip)
  unzip $(ls)
  ;;
esac
for d in $(ls -d)
do
  ( cd "$d" 2>/dev/null && ./configure && make && make install; )
done

【讨论】:

    【解决方案4】:

    我会说,用 ${FILE##*.} 去掉文件的扩展名,然后用 ${FILE%.ext*} 来处理目录名:

    case ${FILE##*.} in
        gz)
        焦油 xf $文件
        cd ${FILE%.tar.gz*}
        ;;
        tgz)
        焦油 xf $文件
        cd ${FILE%.tgz*}
        ;;
        压缩)
        解压 $FILE
        cd ${FILE%.zip*}
        ;;
    esac

    只是一个小问题:如何知道存档中的目录是否与存档本身同名?

    【讨论】:

    • 您也可以为此使用基本名称:cd $(basename $FILE)
    【解决方案5】:
    #! /bin/bash
       #
       # Problem: 
       #  find the path of the "root" folder in an archive
       #
       # Strategy: 
       #  list all folders in the archive.
       #  sort the list to make sure the shortest path is at the top.
       #  print the first line
       # 
       # Weak point:
       #  assumes that tar tf and unzip -l will list files in a certain way
       #  that is: paths ending with / and that the file-list of unzip -l 
       #  is in the fourth column.
       # 
    
       LIST_FILES=
       FILE=$1
       case ${FILE##*.} in
           gz)
           LIST_FILES="tar tf $FILE"
           ;;
           tgz)
           LIST_FILES="tar tf $FILE"
           ;;
           zip)
           LIST_FILES='unzip -l '$FILE' | awk "{print \$4}"'
           ;;
       esac
       ARCHIVE_ROOT=$(
       echo $LIST_FILES | sh |\
           grep '/$'|\
           sort |\
           head -n1
       )
    
       # we should have what we need by now, go ahead and extract the files.
       if [ -d "$ARCHIVE_ROOT" ]; then
           cd "$ARCHIVE_ROOT"
       else
           # there is no path (whoever made the archive is a jerk)
           # ...or the script failed (see weak points)
           exit 1
       fi
    

    【讨论】:

    • 顺便说一句,看看 /usr/bin/lesspipe 一个好的存档检测案例...... esac
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-07-25
    • 1970-01-01
    • 2011-06-05
    • 2013-12-02
    • 2019-11-02
    • 2014-08-02
    • 2013-07-17
    相关资源
    最近更新 更多