bash эквивалент файла Python os.path.normpath? - PullRequest
5 голосов
/ 18 июня 2011

Что за bash эквивалентно os.path.normpath? В частности, я заинтересован в удалении ведущих ./, указанных при выполнении find.

matt@stanley:~/src/libtelnet-0.20/test$ find
.
./Makefile
./Makefile.in
./Makefile.am
...

Ответы [ 7 ]

2 голосов
/ 18 июня 2011

Я изо всех сил пытаюсь найти случай, когда я бы хотел использовать os.path.normpath. В системе с символьными ссылками, такой как unix или Windows, возвращаемое значение может не обозначать один и тот же файл:

$ mkdir /tmp/one /tmp/one/two
$ ln -s /tmp/one/two /tmp/foo
$ python -c 'import os.path; print os.path.normpath("/tmp/foo/..")'
/tmp
$ ls /tmp/foo/..
two

/tmp/foo/.. - это /tmp/one, а не /tmp!

В Linux readlink -- "$filename" нормализует все символические ссылки в пути. Возвращаемое имя файла обозначает тот же файл, что и $filename во время выполнения команды (в противном случае может не произойти, если одна из задействованных символических ссылок будет изменена). Но в большинстве случаев в этом нет необходимости: просто оставьте $filename как есть.

Если вы хотите удалить префикс ./ по косметическим причинам, просто удалите его специально.

filename=${filename#./}
find | sed -e 's!^\./!!'
2 голосов
/ 18 июня 2011

Что ж, для этого вы можете просто направить вывод через sed, вам не нужно нормализовать весь путь:

your_command_goes_here | sed 's?^\./??'

Это избавит от всех последовательностей ./ вначало строки.

Следующая расшифровка демонстрирует это в действии:

pax$ find -name 'qq*sh'
./qq.ksh
./qq.sh
./qq.zsh
./qq2.sh
./qq2.zsh
./qqq/qq.sh

pax$ find -name 'qq*sh' | sed 's?^./??'
qq.ksh
qq.sh
qq.zsh
qq2.sh
qq2.zsh
qqq/qq.sh

Как видите, у меня есть довольно интуитивно понятный стандарт именования для моих временных сценариев оболочки: -)

1 голос
/ 14 ноября 2012

Напишите что-то вроде этого:

normpath() {
    [[ -z "$1" ]] && return

    local skip=0 p o c

    p="$1"
    # check if we have absolute path and if not make it absolute
    [[ "${p:0:1}" != "/" ]] && p="$PWD/$p"

    o=""
    # loop on processing all path elements
    while [[ "$p" != "/" ]]; do
        # retrive current path element
        c="$(basename "$p")"
        # shink our path on one(current) element
        p="$(dirname "$p")"

        # basename/dirname correct handle multimple "/" chars
        # so we can not warry about them

        # skip elements "/./" 
        [[ "$c" == "." ]] && continue
        if [[ "$c" == ".." ]]; then
            # if we have point on parent dir, we must skip next element
            # in other words "a/abc/../c" must become "a/c"
            let "skip += 1"
        elif [[ 0 -lt $skip ]]; then
            # skip current element and decrease skip counter
            let "skip -= 1"
        else
            # this is normal element and we must add it to result
            [[ -n "$o" ]] && o="/$o"
            o="$c$o"
        fi
    done

    # last thing - restore original absolute path sign
    echo "/$o"
}
1 голос
/ 20 июня 2011

Как насчет:

newpath=`echo -n "$oldpath" | python -c 'import sys, os; print os.path.normpath(sys.stdin.readline())'`

Я не думаю, что есть какая-либо встроенная функция bash, которая делает все, что делает normpath в Python. Возможно, вам лучше описать точно , какое преобразование вы хотите выполнить.

1 голос
/ 18 июня 2011

Обычно я делаю это, используя find аргумент -printf.

При поиске по нескольким путям нормально работает:

find path1 path2

При поиске в . нормально работает следующее:

find -printf '%P\n'

Если у вас смешанные пути (например, find path1 path2 .), вам придется использовать sed.

0 голосов
/ 23 июля 2014

Я нашел это: это называется realpath! Введите что-то вроде:

realpath ..   # the most interesting thing

или

realpath .    # equivalent to `pwd' and to `echo $PWD'

и наслаждайтесь!

0 голосов
/ 18 июня 2011

Возможный дубликат здесь . Но если вы просто заинтересованы в том, чтобы снять лидерство ./ вы можете просто сделать

find -type f | sed 's/^\.\///'
...