Lệnh bash / fish để in đường dẫn tuyệt đối đến một tệp


448

Câu hỏi: có lệnh sh / bash / zsh / fish / ... đơn giản để in đường dẫn tuyệt đối của bất kỳ tệp nào tôi cho nó ăn không?

Trường hợp sử dụng: Tôi đang ở trong thư mục /a/bvà tôi muốn in đường dẫn đầy đủ đến tệp ctrên dòng lệnh để tôi có thể dễ dàng dán nó vào chương trình khác : /a/b/c. Đơn giản, nhưng một chương trình nhỏ để làm điều này có thể giúp tôi tiết kiệm khoảng 5 giây hoặc lâu hơn khi xử lý các đường dẫn dài, mà cuối cùng lại thêm vào. Vì vậy, điều làm tôi ngạc nhiên là tôi không thể tìm thấy một tiện ích tiêu chuẩn để làm điều này - có thực sự không có?

Đây là một triển khai mẫu, abspath.py:

#!/usr/bin/python
# Author: Diggory Hardy <diggory.hardy@gmail.com>
# Licence: public domain
# Purpose: print the absolute path of all input paths

import sys
import os.path
if len(sys.argv)>1:
    for i in range(1,len(sys.argv)):
        print os.path.abspath( sys.argv[i] )
    sys.exit(0)
else:
    print >> sys.stderr, "Usage: ",sys.argv[0]," PATH."
    sys.exit(1)

Tôi sẽ lập luận rằng câu trả lời của @ DennisWilliamson (sử dụng tùy chọn -m) là tốt hơn (thường) có tính di động cao hơn và làm việc với các tệp không tồn tại.
TTT

Hoặc câu trả lời của Flimm; cả hai đều là giải pháp tốt. Tuy nhiên, Bannier trả lời tốt nhất câu hỏi ban đầu của tôi .
dhardy

3
Người dùng OSX: xem câu trả lời này
Ian

Câu trả lời:


561

Hãy thử realpath.

$ realpath example.txt
/home/username/example.txt

133
+1, chương trình rất hay. Nhưng lưu ý rằng đó là một lệnh bên ngoài (không phải là vỏ tích hợp) và có thể không có trong mọi hệ thống theo mặc định, tức là bạn có thể cần phải cài đặt nó. Trong Debian nó nằm trong một gói riêng có cùng tên.
Roman Cheplyaka

5
Tôi đã thêm vào đường dẫn của mình a realpathbao gồm: github.com/westonruter/misc-cli-tools/blob/master/realpath
Weston Ruter

1
@Flimm: Nó vẫn sẽ cung cấp cho bạn một đường dẫn hợp lệ với một số đường dẫn tương đối. Nếu bạn muốn biết về sự tồn tại của tập tin, hãy sử dụng một công cụ khác như eg test.
Benjamin Bannier

14
@Dalin: Hãy thử cài đặt coreutils. Nhị phân được đặt tên là grealpath.
Toni Penya-Alba

5
Công cụ này đã được giới thiệu trong GNU coreutils 8.15 (năm 2012), vì vậy nó khá mới.
marbu

317

Hãy thử readlinksẽ giải quyết các liên kết tượng trưng:

readlink -e /foo/bar/baz

50
Tôi thà sử dụng '-f' thay vì '-e' để chúng ta có thể thấy đường dẫn tuyệt đối của một tệp không tồn tại.
hluk

5
Điều này có vẻ như đơn giản nhất đối với tôi, trong khi cũng có thể mang theo. readlink là cổng của lõi gnu, vì vậy nó sẽ được cài đặt trên hầu hết mọi bản phân phối linux, ngoại trừ một số bản nhúng.
catphive

14
Dường như với tôi đó -mlà lựa chọn tốt nhất để sử dụng.
Matt Joiner

1
@Dalin: /usr/bin/readlinktrên Mavericks. Hay bạn có nghĩa là những tùy chọn đó không được tìm thấy trên OS X? Nó dường như là một phiên bản BSD còi cọc ...: p
iconoclast

14
@iconoclast Những tùy chọn đó không khả dụng trên OSX và theo trang chủ BSD readlink: only the target of the symbolic link is printed. If the given argument is not a symbolic link, readlink will print nothing and exit with an error, vì vậy, đường dẫn đọc sẽ không hoạt động cho mục đích này trên OSX
SnoringFrog

257
#! /bin/sh
echo "$(cd "$(dirname "$1")"; pwd -P)/$(basename "$1")"

8
Đừng quên trích dẫn tất cả mọi thứ. Nếu bạn không hiểu tại sao, hãy thử chương trình của bạn trên một tệp a b(hai khoảng trắng giữa a và b, SO ăn một trong số chúng).
Roman Cheplyaka

1
cũng thử cái này trên "/" nó biến thành "///"
George

35
giải pháp POSIX duy nhất cho đến nay không yêu cầu bạn phải viết và biên dịch một tệp thực thi vì readlink và realpath không phải là POSIX
Ciro Santilli 郝海东 冠状 病 法轮功

25
Tôi đã từng function realpath { echo $(cd $(dirname $1); pwd)/$(basename $1); }tự tạo cho mình một realpathlệnh (câu trả lời hiện được chấp nhận) trên OS X. Cảm ơn!
James Bedford

1
Tôi đã sử dụng phương pháp này để xác định tên tệp nhật ký cho các tập lệnh:LOG=$(echo $(cd $(dirname $0); pwd)/$(basename $0 .sh).log)
DrStrangepork

84

Quên về readlinkrealpathcó thể hoặc không thể được cài đặt trên hệ thống của bạn.

Mở rộng về câu trả lời của dogbane ở trên, nó được thể hiện dưới dạng một hàm:

#!/bin/bash
get_abs_filename() {
  # $1 : relative filename
  echo "$(cd "$(dirname "$1")" && pwd)/$(basename "$1")"
}

sau đó bạn có thể sử dụng nó như thế này:

myabsfile=$(get_abs_filename "../../foo/bar/file.txt")

Làm thế nào và tại sao nó hoạt động?

Giải pháp khai thác thực tế là lệnh tích hợp Bash pwdsẽ in đường dẫn tuyệt đối của thư mục hiện tại khi được gọi mà không có đối số.

Tại sao tôi thích giải pháp này?

Nó là thiết bị di động và không yêu cầu readlinkhoặc realpaththường không tồn tại trên bản cài đặt mặc định của một bản phân phối Linux / Unix cụ thể.

Điều gì xảy ra nếu dir không tồn tại?

Như đã cho ở trên, hàm sẽ thất bại và in trên stderr nếu đường dẫn thư mục đã cho không tồn tại. Đây có thể không phải là những gì bạn muốn. Bạn có thể mở rộng chức năng để xử lý tình huống đó:

#!/bin/bash
get_abs_filename() {
  # $1 : relative filename
  if [ -d "$(dirname "$1")" ]; then
    echo "$(cd "$(dirname "$1")" && pwd)/$(basename "$1")"
  fi
}

Bây giờ nó sẽ trả về một chuỗi rỗng nếu một thư mục cha không tồn tại.

Làm thế nào để bạn xử lý dấu vết '..' hoặc '.' đầu vào?

Vâng, nó đưa ra một con đường tuyệt đối trong trường hợp đó, nhưng không phải là một con đường tối thiểu. Nó sẽ trông như:

/Users/bob/Documents/..

Nếu bạn muốn giải quyết '..', bạn sẽ cần tạo tập lệnh như:

get_abs_filename() {
  # $1 : relative filename
  filename=$1
  parentdir=$(dirname "${filename}")

  if [ -d "${filename}" ]; then
      echo "$(cd "${filename}" && pwd)"
  elif [ -d "${parentdir}" ]; then
    echo "$(cd "${parentdir}" && pwd)/$(basename "${filename}")"
  fi
}

Chức năng tốt, nhưng rõ ràng bạn không hiểu câu hỏi. Tôi muốn một cái gì đó để sử dụng tương tác, không phải kịch bản.
dhardy

3
Tôi muốn thêm rằng realpathđến từ gói coreutils, cũng chứa các công cụ như who, touchhoặc cat. Đó là một bộ công cụ GNU khá độc đáo, vì vậy bạn có thể khá chắc chắn rằng nó được cài đặt trên hầu hết mọi máy dựa trên linux. Điều đó nói rằng, bạn đã đúng: có 2 vấn đề với nó: i) bạn có thể sẽ bỏ lỡ nó khi cài đặt mặc định các hệ thống unix GNU (như OpenBSD) ii) các công cụ này đã được giới thiệu trong phiên bản 8.15 (vì vậy nó khá mới, từ năm 2012), vì vậy bạn sẽ bỏ lỡ nó trên các hệ thống ổn định lâu dài (như RHEL 6).
marbu

1
Chà, có vẻ như ít nhất là Continuum Analytics (nhà sản xuất phân phối Anaconda Python ) thích câu trả lời này. Nó được triển khai (với một tham chiếu liên kết trở lại đây) trong tập lệnh "kích hoạt" của chúng , được sử dụng để kích hoạt các môi trường ảo được tạo bởi công cụ conda. Vì vậy, một trong những tốt!
wjv

1
Điều này chỉ hoạt động cho các thư mục (vì không có ai khác) và không thể đối phó với ".." và ".". Xem câu trả lời của tôi sẽ xử lý mọi thứ: stackoverflow.com/a/23002317/2709
Alexander Klimetschek

3
@marbu realpath không có trên Ubuntu 14.04 hoặc trên Debian Wheezy. Nó có thể trở nên hơi chuẩn theo thời gian, nhưng chắc chắn không phải bây giờ. Cũng lưu ý rằng OP không nói gì về linux hoặc GNU. Bash được sử dụng rộng rãi hơn thế.
mc0e

76
$ readlink -m FILE
/path/to/FILE

Điều này tốt hơn readlink -e FILEhoặc realpath, bởi vì nó hoạt động ngay cả khi tệp không tồn tại.


Đẹp. Điều này cũng hoạt động trên các tập tin / thư mục tồn tại nhưng không phải là liên kết tượng trưng.
quietmint 30/12/13

Tôi có sẵn readlink trên OS X 10.9 (Mavericks), vì vậy đây chắc chắn là câu trả lời tốt nhất ở đây.
Kenneth Hoste

6
@Kennethhoste: -mtùy chọn không khả dụng trên Mavericks.
iconoclast

2
Chắc chắn nó không phải trên bản cài đặt DEFAULT OSX.
Fran Marzoa

hoạt động trên linux (CentOS) cảm ơn bạn, vì realpath không tồn tại cho nó
jimh

65

Đường dẫn tương đối này đến hàm shell trình chuyển đổi đường dẫn tuyệt đối

  • không yêu cầu tiện ích (chỉ cdpwd)
  • làm việc cho các thư mục và tập tin
  • xử lý ...
  • xử lý khoảng trắng trong thư mục hoặc tên tệp
  • yêu cầu tập tin hoặc thư mục tồn tại
  • trả về không có gì nếu không có gì tồn tại ở đường dẫn đã cho
  • xử lý các đường dẫn tuyệt đối làm đầu vào (chuyển chúng qua cơ bản)

Mã số:

function abspath() {
    # generate absolute path from relative path
    # $1     : relative filename
    # return : absolute path
    if [ -d "$1" ]; then
        # dir
        (cd "$1"; pwd)
    elif [ -f "$1" ]; then
        # file
        if [[ $1 = /* ]]; then
            echo "$1"
        elif [[ $1 == */* ]]; then
            echo "$(cd "${1%/*}"; pwd)/${1##*/}"
        else
            echo "$(pwd)/$1"
        fi
    fi
}

Mẫu vật:

# assume inside /parent/cur
abspath file.txt        => /parent/cur/file.txt
abspath .               => /parent/cur
abspath ..              => /parent
abspath ../dir/file.txt => /parent/dir/file.txt
abspath ../dir/../dir   => /parent/dir          # anything cd can handle
abspath doesnotexist    =>                      # empty result if file/dir does not exist
abspath /file.txt       => /file.txt            # handle absolute path input

Lưu ý: Điều này dựa trên các câu trả lời từ nolan6000bsingh , nhưng sửa trường hợp tệp.

Tôi cũng hiểu rằng câu hỏi ban đầu là về một tiện ích dòng lệnh hiện có. Nhưng vì đây có vẻ là câu hỏi về stackoverflow cho điều đó bao gồm các tập lệnh shell muốn có phụ thuộc tối thiểu, tôi đặt giải pháp tập lệnh này ở đây, vì vậy tôi có thể tìm thấy nó sau :)


Cảm ơn. Đó là những gì tôi đi với OSX
Greg

Điều này không hoạt động đối với các thư mục có khoảng trắng, nghĩa là: $ abspath 'a b c/file.txt'Đó là vì đối số cdkhông được trích dẫn. Để khắc phục điều này, thay vì trích dẫn toàn bộ đối số echo(có lý do nào cho các trích dẫn này không?) Chỉ trích dẫn các đối số đường dẫn. Tức là thay thế echo "$(cd ${1%/*}; pwd)/${1##*/}"bằng echo $(cd "${1%/*}"; pwd)/${1##*/}.
george

@george Cảm ơn bạn đã lưu ý, tôi đã sửa nó.
Alexander Klimetschek

1
Tôi đã xem qua hàng tá các giải pháp nửa vời và đây chắc chắn là giải pháp bash chỉ chính xác và ngắn gọn nhất. Bạn có thể làm mỏng nó hơn nữa bằng cách thay thế echo "$(cd "$1"; pwd)"bằng (cd "$1"; pwd). Không cần tiếng vang ở đây.
Sáu

@Six Đúng, cập nhật. Niềng răng ( ... )vẫn cần thiết, vì vậy điều này cdxảy ra trong một mạng con, vì chúng tôi không muốn thay đổi thư mục làm việc cho bất kỳ người gọi nào abspath.
Alexander Klimetschek

24

Các findlệnh có thể giúp

find $PWD -name ex*
find $PWD -name example.log

Liệt kê tất cả các tệp trong hoặc bên dưới thư mục hiện tại với các tên khớp với mẫu. Bạn có thể đơn giản hóa nó nếu bạn sẽ chỉ nhận được một vài kết quả (ví dụ: thư mục gần cuối cây chứa vài tệp), chỉ

find $PWD

Tôi sử dụng cái này trên Solaris 10, không có các tiện ích khác được đề cập.


1
tôi đã không mò mẫm nhận xét này trong lần đọc đầu tiên; điểm mấu chốt ở đây là nếu bạn đưa ra một đường dẫn tuyệt đối cho lệnh find thì nó sẽ đưa ra kết quả theo đường dẫn tuyệt đối. vì vậy, sử dụng $ PWD là đường dẫn tuyệt đối của vị trí của bạn để bạn có được đầu ra là tuyệt đối.
simbo1905

4
Nếu bạn dựa vào PWD, bạn có thể chỉ cần sử dụng $PWD/$filename.
jonny

Cách tiếp cận này có thể được cải thiện khi sử dụng -maxdepth 1. Cũng đừng quên trích dẫn - các vấn đề bảo mật tiềm ẩn ở đây, tùy thuộc vào cách bạn sử dụng phương pháp này.
mc0e

1
@jonny: Tên tệp $ PWD / $ không thành công nếu tên tệp $ đã tuyệt đối.
mc0e

Điều này không thành công nếu tên tệp được đưa ra là "./filename.txt" (với dấu chấm và dấu gạch chéo hàng đầu).
Đánh dấu Stosberg

15

Nếu bạn không có tiện ích readlink hoặc realpath hơn bạn có thể sử dụng chức năng sau hoạt động trong bash và zsh (không chắc chắn về phần còn lại).

abspath () { case "$1" in /*)printf "%s\n" "$1";; *)printf "%s\n" "$PWD/$1";; esac; }

Điều này cũng hoạt động cho các tập tin không tồn tại (cũng như chức năng python os.path.abspath).

Thật không may abspath ./../somefile, không thoát khỏi các dấu chấm.


1
Trông xách tay cho tôi. Mặt khác, sẽ phá vỡ ví dụ trên một tên tệp có chứa một dòng mới.
Roman Cheplyaka

1
Để cải thiện hơn nữa, thay thế echo "$1"bằng printf "%s\n" "$1"(cùng với tiếng vang thứ hai). echocó thể giải thích dấu gạch chéo ngược bên trong các đối số của nó.
Roman Cheplyaka

Một lần nữa, bạn đã đúng! Thực sự, hành vi của lệnh echo trong zsh khác với bash.
hluk

1
Nói một cách chính xác, dưới hành vi POSIX của echo không được xác định nếu các đối số có dấu gạch chéo ngược. Tuy nhiên, nó được định nghĩa trong phần mở rộng XSI (cụ thể là echo nên diễn giải các chuỗi thoát). Nhưng cả bash và zsh đều khác xa so với tuân thủ POSIX ...
Roman Cheplyaka

Xin lỗi, nhưng tôi không thấy vấn đề. Tôi đã cung cấp một câu trả lời dưới dạng một tập lệnh với nhiều tính năng hơn và nó không cần phải được sử dụng trong tập lệnh shell.
dhardy

10

Đây là một chức năng chỉ zsh mà tôi thích vì sự nhỏ gọn của nó. Nó sử dụng công cụ sửa đổi mở rộng 'A' - xem zshExn (1).

realpath() { for f in "$@"; do echo ${f}(:A); done }

Wow đó là một giải pháp tao nhã !!
ShellFish

6

Có điều nói chung không có như các absolute path vào một tập tin (tuyên bố này có nghĩa rằng có thể có nhiều hơn một nói chung, do đó việc sử dụng các mạo từ xác định các không phù hợp). An absolute pathlà bất kỳ đường dẫn nào bắt đầu từ gốc "/" và chỉ định một tệp mà không có sự mơ hồ độc lập với thư mục làm việc. (Xem ví dụ wikipedia ).

A relative pathlà một đường dẫn sẽ được giải thích bắt đầu từ một thư mục khác. Nó có thể là thư mục làm việc nếu nó đang relative pathbị một ứng dụng thao túng (mặc dù không nhất thiết). Khi nó nằm trong một liên kết tượng trưng trong một thư mục, nó thường được dự định là có liên quan đến thư mục đó (mặc dù người dùng có thể có ý định sử dụng khác).

Do đó, một đường dẫn tuyệt đối chỉ là một đường dẫn liên quan đến thư mục gốc.

Một đường dẫn (tuyệt đối hoặc tương đối) có thể có hoặc không chứa các liên kết tượng trưng. Nếu không, nó cũng hơi không thay đổi trong cấu trúc liên kết, nhưng điều này không nhất thiết là bắt buộc hoặc thậm chí là mong muốn. Một số người gọi canonical path(hoặc canonical file namehay resolved path) một absolute pathtrong đó tất cả liên kết tượng trưng đã được giải quyết, tức là đã được thay thế bằng một đường dẫn đến whetever họ liên kết tới. Các lệnh realpathreadlinkcả hai đều tìm kiếm một đường dẫn chính tắc, nhưng chỉ realpathcó một tùy chọn để có được một đường dẫn tuyệt đối mà không cần giải quyết các liên kết tượng trưng (cùng với một số tùy chọn khác để có được các loại đường dẫn khác nhau, tuyệt đối hoặc liên quan đến một số thư mục).

Điều này kêu gọi một số nhận xét:

  1. liên kết tượng trưng chỉ có thể được giải quyết nếu bất cứ điều gì chúng được cho là liên kết đến đã được tạo, điều này rõ ràng không phải luôn luôn như vậy. Các lệnh realpathreadlinkcó các tùy chọn để giải thích cho điều đó.
  2. một thư mục trên một đường dẫn sau này có thể trở thành một liên kết tượng trưng, ​​có nghĩa là đường dẫn đó không còn nữa canonical. Do đó khái niệm phụ thuộc vào thời gian (hoặc môi trường).
  3. ngay cả trong trường hợp lý tưởng, khi tất cả các liên kết tượng trưng có thể được giải quyết, vẫn có thể có nhiều hơn một canonical pathđến một tệp, vì hai lý do:
    • phân vùng chứa tệp có thể đã được gắn đồng thời ( ro) trên một số điểm gắn kết.
    • có thể có các liên kết cứng đến tệp, có nghĩa là về cơ bản tệp tồn tại trong một số thư mục khác nhau.

Do đó, ngay cả với định nghĩa hạn chế hơn nhiều canonical path, có thể có một số đường dẫn chính tắc đến một tệp. Điều này cũng có nghĩa là vòng loại canonicalcó phần không thỏa đáng vì nó thường bao hàm một khái niệm về tính độc đáo.

Điều này mở rộng một cuộc thảo luận ngắn gọn về chủ đề trong câu trả lời cho một câu hỏi tương tự khác tại Bash: lấy đường dẫn tuyệt đối cho tương đối

Kết luận của tôi là realpathđược thiết kế tốt hơn và linh hoạt hơn nhiều readlink. Việc sử dụng duy nhất readlinkkhông được bao phủ bởi realpathcuộc gọi mà không có tùy chọn trả về giá trị của một liên kết tượng trưng.


Tôi không ngại bị hạ thấp, nhưng tôi muốn hiểu lý do tại sao để tôi có thể học được điều gì đó, về kỹ thuật hoặc liên quan đến những gì được coi là thực hành đúng trên trang web. Chà ... ít nhất nó đã khiến tôi phải đăng ký với Meta Stack Overflow để hiểu rõ hơn về xã hội học địa phương. Tôi khuyên bạn nên nó. - Tuy nhiên, nếu bất cứ ai có ý kiến ​​về sự không phù hợp trong câu trả lời của tôi, tôi quan tâm.
babou

1
(a) câu hỏi có câu trả lời hợp lệ từ 2 + 1/2 năm trước, (b) có một đường dẫn tuyệt đối (duy nhất) tương ứng với một đường dẫn tương đối (đó là những gì tôi muốn), mặc dù có thể không phải là một tệp như bạn chỉ ra. BTW bất kỳ ý kiến ​​về realpathvs readlinkhoặc thậm chí về các liên kết tượng trưng là dư thừa với những gì tôi yêu cầu.
dhardy

1
Nhận xét thứ hai: câu trả lời ngắn thường rất hữu ích hơn bài giảng dài. Tràn ngăn xếp thường được sử dụng để đặt câu hỏi cụ thể.
dhardy

5
1- thực tế là một câu hỏi đã có câu trả lời hợp lệ tuy nhiên không có nghĩa là nó đã bị đóng. Các câu hỏi không dành cho chỉ sử dụng cá nhân. Thật vậy, có những huy hiệu cho các câu trả lời thu thập nhiều phiếu hơn so với câu trả lời được xác thực. Và với các công cụ mới, câu trả lời "tốt nhất" có thể thay đổi theo thời gian. Nhiều người sử dụng câu trả lời cũ truy cập thông qua tìm kiếm trên web.
babou

1
2 - Bạn nhấn mạnh rằng có một đường dẫn tuyệt đối (đơn) tương ứng với một đường dẫn tương đối . Mặc dù tôi đoán ý của bạn là "tương ứng", nghĩa là một đường dẫn xuất phát từ bản gốc thông qua một tập hợp các phép biến đổi nhất định, câu lệnh của bạn vẫn không chính xác. Có một con đường kinh điển "tương ứng" duy nhất. Từ này canonicalđề cập chính xác đến tính duy nhất này liên quan đến một tập hợp các biến đổi. Nhưng, ví dụ, / dev / cdrom là một đường dẫn tuyệt đối hoàn toàn tốt, mặc dù nó thực sự là một liên kết đến / dev / sr0. Cả hai đều chỉ đến cùng một thiết bị. Câu trả lời ban đầu của tôi chỉ vào một bài viết web có liên quan.
babou

5

Câu dogbane trả lời với mô tả những gì đang xảy ra:

#! /bin/sh
echo "$(cd "$(dirname "$1")"; pwd)/$(basename "$1")"

Giải trình:

  1. Kịch bản này lấy đường dẫn tương đối làm đối số "$1"
  2. Sau đó, chúng tôi nhận được phần dirname của đường dẫn đó (bạn có thể chuyển dir hoặc tệp vào tập lệnh này):dirname "$1"
  3. Sau đó, chúng tôi cd "$(dirname "$1")vào thư mục tương đối này và nhận đường dẫn tuyệt đối cho nó bằng cách chạy pwdlệnh shell
  4. Sau đó, chúng tôi nối tên cơ sở vào đường dẫn tuyệt đối:$(basename "$1")
  5. Như bước cuối cùng chúng ta echo

2

Đối với các thư mục dirnameđược tăng gấp ba cho ../và trả lại ./.

Chức năng của nolan6000 có thể được sửa đổi để khắc phục điều đó:

get_abs_filename() {
  # $1 : relative filename
  if [ -d "${1%/*}" ]; then
    echo "$(cd ${1%/*}; pwd)/${1##*/}"
  fi
}

1
Chào mừng đến với SO! Đối với những thay đổi và nhận xét nhỏ, việc thêm nhận xét vào câu trả lời hiện có có thể phù hợp hơn là thêm câu trả lời, đặc biệt nếu câu trả lời được sao chép này thiếu nhiều thông tin khác của câu trả lời ban đầu. Khi bạn đã thu thập được một chút danh tiếng, bạn có thể thêm nhận xét vào câu trả lời của người khác. Ngay bây giờ, hãy cố gắng thu thập danh tiếng bằng cách đặt câu hỏi độc đáo, có giá trị hoặc cung cấp độc lập, câu trả lời tốt.
cfi

1
Vì bạn đang đề cập đến câu trả lời của nolan6000, xin lưu ý rằng người đăng bài đã nhận xét rằng anh ta sẽ không chấp nhận câu trả lời của nolan6000 vì anh ta không tìm kiếm kịch bản. Vì vậy, nghiêm túc nói câu trả lời của bạn không trả lời câu hỏi.
cfi

chức năng có thể được thêm vào .profilevà do đó có sẵn để sử dụng tương tác.
adib

Điều này sẽ không hoạt động nếu $1là một tên tệp đơn giản: get_abs_filename foo-> không có gì (hoặc <current_dir>/foo/foonếu foolà một thư mục).
ivan_pozdeev

2

Đây không phải là một câu trả lời cho câu hỏi, nhưng dành cho những người viết kịch bản:

echo `cd "$1" 2>/dev/null&&pwd||(cd "$(dirname "$1")";pwd|sed "s|/*\$|/${1##*/}|")`

nó xử lý / .. ./ vv chính xác. Tôi dường như cũng làm việc trên OSX


2

Tôi đã đặt đoạn script sau trên hệ thống của mình và tôi gọi nó là bí danh bash khi tôi muốn nhanh chóng lấy đường dẫn đầy đủ đến một tệp trong thư mục hiện tại:

#!/bin/bash
/usr/bin/find "$PWD" -maxdepth 1 -mindepth 1 -name "$1"

Tôi không chắc tại sao, nhưng, trên OS X khi được gọi bởi một tập lệnh "$ PWD" mở rộng đến đường dẫn tuyệt đối. Khi lệnh find được gọi trên dòng lệnh, thì không. Nhưng nó làm những gì tôi muốn ... tận hưởng.


$PWDluôn luôn có đường dẫn tuyệt đối của thư mục làm việc. Ngoài ra, findsẽ không tha thứ cho dấu gạch chéo, vì vậy bạn không trả lời câu hỏi như đã hỏi. Một cách nhanh hơn để làm những gì bạn muốn làm chỉ đơn giản làecho "$PWD/$1"
Adam Katz

2

Đơn giản nhất nếu bạn muốn chỉ sử dụng nội dung có lẽ là:

find `pwd` -name fileName

Chỉ có thêm hai từ để gõ và điều này sẽ hoạt động trên tất cả các hệ thống unix, cũng như OSX.


Tôi sẽ thêm -maxdepth 1trước -name(giả sử tập tin nằm trong thư mục hiện tại). Nếu không có nó, nó sẽ hoạt động với các tệp trong bất kỳ thư mục con nào của pwd, nhưng không phải với các tệp khác.
Walter Tross

Thật vậy, bạn đã đúng, câu hỏi đã chỉ định rằng tệp sẽ nằm trong thư mục hiện tại. Bạn có ý nghĩa gì "nhưng không phải với người khác"?
Arj

Tôi có nghĩa là findsẽ không tìm thấy một tập tin bên ngoài cây thư mục bên dưới pwd. Ví dụ, nếu bạn cố gắng find . -name ../existingFile, nó thất bại.
Walter Tross

Đủ công bằng, vâng, điều này sẽ cho rằng bạn muốn in toàn bộ đường dẫn của tệp trong cwd của bạn (theo câu hỏi ban đầu) hoặc bất cứ nơi nào trong cây cwd của bạn (không phải trong câu hỏi ban đầu).
Arj

1
#! /bin/bash

file="$@"
realpath "$file" 2>/dev/null || eval realpath $(echo $file | sed 's/ /\\ /g')

Điều này bù đắp cho những thiếu sót của realpath, lưu trữ nó trong một kịch bản shell fullpath. Bây giờ bạn có thể gọi:

$ cd && touch a\ a && rm A 2>/dev/null 
$ fullpath "a a"
/home/user/a a
$ fullpath ~/a\ a
/home/user/a a
$ fullpath A
A: No such file or directory.

Nó giải quyết cái gì? realpath "foo bar"-> /home/myname/foo bar. Nếu bạn không thể bận tâm trích dẫn các đối số dòng lệnh, đó không phải realpathlà lỗi.
ivan_pozdeev

Đồng ý, đó là một gói bọc tiện lợi.
ShellFish

1

Một cách khác để có được đường dẫn tuyệt đối trong Ruby :

realpath() {ruby -e "require 'Pathname'; puts Pathname.new('$1').realpath.to_s";}

Hoạt động không có đối số (thư mục hiện tại) và đường dẫn tệp hoặc thư mục tương đối và tuyệt đối dưới dạng agument.


0

Trả lời với Homebrew

realpathlà câu trả lời tốt nhất, nhưng nếu bạn chưa cài đặt nó, trước tiên bạn phải chạy brew install coreutilsnó sẽ cài đặt coreutils với nhiều chức năng tuyệt vời. Viết một chức năng tùy chỉnh và xuất nó là quá nhiều công việc và có nguy cơ lỗi cho một cái gì đó như thế này, đây là hai dòng:

$ brew install coreutils
$ realpath your-file-name.json 

-1

Này các bạn tôi biết đó là một chủ đề cũ nhưng tôi chỉ đăng bài này để tham khảo cho bất kỳ ai khác đã truy cập như tôi. Nếu tôi hiểu câu hỏi chính xác, tôi nghĩ locate $filenamelệnh. Nó hiển thị đường dẫn tuyệt đối của tệp được cung cấp, nhưng chỉ khi nó tồn tại.


4
locatelà một tiện ích để tìm kiếm các tập tin / đường dẫn theo tên. Nó có thể thực hiện công việc nhưng cũng có thể tìm thấy các kết quả khớp khác và có thể không tìm thấy tệp hiện có mà không gọi updatedblà root trước.
dhardy
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.