perintah bash / fish untuk mencetak path absolut ke file

448

Pertanyaan: apakah ada perintah sh / bash / zsh / fish / ... sederhana untuk mencetak jalur absolut dari file mana pun yang saya beri makan?

Kasus penggunaan: Saya dalam direktori /a/bdan saya ingin mencetak path lengkap ke file cpada baris perintah sehingga saya dapat dengan mudah sisipkan ke program lain: /a/b/c. Sederhana, namun sedikit program untuk melakukan ini mungkin bisa menyelamatkan saya 5 atau lebih detik ketika datang untuk menangani jalur panjang, yang pada akhirnya bertambah. Jadi itu mengejutkan saya bahwa saya tidak dapat menemukan utilitas standar untuk melakukan ini - apakah benar-benar tidak ada?

Berikut contoh implementasi, abspath.py:

#!/usr/bin/python
# Author: Diggory Hardy <[email protected]>
# 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)
dhardy
sumber
Saya berpendapat bahwa jawaban @ DennisWilliamson (menggunakan opsi -m) lebih unggul karena (biasanya) lebih portabel dan bekerja dengan file yang tidak ada.
TTT
Atau jawaban Flimm; keduanya adalah solusi yang bagus. Namun Bannier menjawab pertanyaan asli saya yang terbaik.
dhardy
3
Pengguna OSX: lihat jawaban ini
Ian
Kemungkinan duplikat Bash: ambil jalur absolut yang diberikan relatif
pengguna

Jawaban:

561

Coba realpath.

$ realpath example.txt
/home/username/example.txt
Benjamin Bannier
sumber
133
+1, program yang sangat bagus. Tetapi perhatikan bahwa ini adalah perintah eksternal (bukan built-in shell) dan mungkin tidak ada di setiap sistem secara default, yaitu Anda mungkin perlu menginstalnya. Dalam Debian ia berada dalam paket terpisah dengan nama yang sama.
Roman Cheplyaka
5
Saya menambahkan ke jalur saya yang realpathterdiri dari: github.com/westonruter/misc-cli-tools/blob/master/realpath
Weston Ruter
1
@ Flimm: Ini masih akan memberi Anda jalur yang valid diberikan beberapa jalur relatif. Jika Anda ingin tahu tentang keberadaan file, gunakan alat lain seperti misalnya tes.
Benjamin Bannier
14
@ Dalin: Coba pasang coreutils. Biner ini bernama grealpath.
Toni Penya-Alba
5
Alat ini diperkenalkan di GNU coreutils 8.15 (pada 2012), jadi ini cukup baru.
marbu
317

Coba readlinkyang akan menyelesaikan tautan simbolik:

readlink -e /foo/bar/baz
Dijeda sampai pemberitahuan lebih lanjut.
sumber
50
Saya lebih suka menggunakan '-f' daripada '-e' sehingga kita dapat melihat path absolut dari file yang tidak ada.
hluk
5
Ini sepertinya yang paling sederhana bagi saya, sementara juga portabel. readlink adalah port dari gnu coreutils, jadi itu akan diinstal pada hampir semua distribusi linux, kecuali untuk beberapa yang tertanam.
catphive
14
Menurut saya itu -madalah pilihan terbaik untuk digunakan.
Matt Joiner
1
@Dalin: /usr/bin/readlinkdi Mavericks. Atau maksud Anda opsi-opsi itu tidak ditemukan di OS X? Tampaknya menjadi versi BSD kerdil ...: p
iconoclast
14
@iconoclast Opsi-opsi itu tidak tersedia di OSX, dan sesuai dengan readlinkmanual BSD 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:, jadi readlink tidak akan berfungsi untuk tujuan ini di OSX
SnoringFrog
257
#! /bin/sh
echo "$(cd "$(dirname "$1")"; pwd -P)/$(basename "$1")"
dogbane
sumber
8
Jangan lupa mengutip semua barang. Jika Anda tidak mengerti mengapa, coba program Anda pada file a b(dua spasi antara a dan b, jadi makanlah salah satunya).
Roman Cheplyaka
1
juga coba ini pada "/" itu berubah menjadi "///"
George
35
satu-satunya solusi POSIX sejauh ini yang tidak mengharuskan Anda untuk menulis dan mengkompilasi yang dapat dieksekusi karena readlink dan realpath bukan POSIX
Ciro Santilli
25
Saya dulu function realpath { echo $(cd $(dirname $1); pwd)/$(basename $1); }membuat sendiri realpathperintah (jawaban yang saat ini diterima) di OS X. Terima kasih!
James Bedford
1
Saya menggunakan metode ini untuk mendefinisikan nama file log untuk skrip:LOG=$(echo $(cd $(dirname $0); pwd)/$(basename $0 .sh).log)
DrStrangepork
84

Lupakan readlinkdan realpathyang mungkin atau mungkin tidak diinstal pada sistem Anda.

Memperluas jawaban dogbane di atas di sini dinyatakan sebagai fungsi:

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

Anda dapat menggunakannya seperti ini:

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

Bagaimana dan mengapa ini bekerja?

Solusinya mengeksploitasi fakta bahwa Bash built-in pwdcommand akan mencetak path absolut dari direktori saat ini ketika dipanggil tanpa argumen.

Mengapa saya suka solusi ini?

Ini portabel dan tidak memerlukan keduanya readlinkatau realpathyang sering tidak ada pada instalasi default distro Linux / Unix yang diberikan.

Bagaimana jika dir tidak ada?

Seperti yang diberikan di atas, fungsi akan gagal dan mencetak pada stderr jika jalur direktori yang diberikan tidak ada. Ini mungkin bukan yang Anda inginkan. Anda dapat memperluas fungsi untuk menangani situasi itu:

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

Sekarang ia akan mengembalikan string kosong jika salah satu dir induk tidak ada.

Bagaimana Anda menangani trailing '..' atau '.' dalam input?

Yah, itu memang memberikan jalan absolut dalam kasus itu, tetapi tidak sedikit. Ini akan terlihat seperti:

/Users/bob/Documents/..

Jika Anda ingin menyelesaikan '..' Anda harus membuat skrip seperti:

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
}
peterh
sumber
Fungsinya bagus, tetapi ternyata Anda tidak mengerti pertanyaan itu. Saya menginginkan sesuatu untuk penggunaan interaktif, bukan skrip.
dhardy
3
Saya ingin menambahkan yang realpathberasal dari paket coreutils, yang juga berisi alat-alat seperti who, touchatau cat. Ini adalah seperangkat alat GNU yang cukup standar, sehingga Anda dapat yakin bahwa ini diinstal pada hampir semua mesin berbasis linux. Yang mengatakan, Anda benar: ada 2 masalah dengan itu: i) Anda mungkin akan melewatkannya di instal default pada sistem non GNU unix (seperti OpenBSD) ii) alat ini diperkenalkan di versi 8.15 (jadi ini cukup baru, mulai 2012), jadi Anda akan melewatkannya di sistem stabil jangka panjang (seperti RHEL 6).
marbu
1
Yah, tampaknya setidaknya Continuum Analytics (pembuat distribusi Anaconda Python ) menyukai jawaban ini. Ini diimplementasikan (dengan referensi yang menghubungkan kembali ke sini) dalam skrip "aktifkan" mereka , yang digunakan untuk mengaktifkan lingkungan virtual yang dibuat oleh alat conda. Jadi ... bagus!
wjv
1
Ini hanya berfungsi untuk direktori (karena tidak ada yang lain) dan tidak dapat mengatasi ".." dan ".". Lihat jawaban saya yang harus menangani semuanya: stackoverflow.com/a/23002317/2709
Alexander Klimetschek
3
@marbu realpath tidak ada di Ubuntu 14.04, atau di Debian Wheezy. Ini mungkin menjadi agak standar dari waktu ke waktu, tetapi tentu saja tidak sekarang. Perhatikan juga bahwa OP tidak mengatakan apa-apa tentang linux atau GNU. Bash lebih banyak digunakan daripada itu.
mc0e
76
$ readlink -m FILE
/path/to/FILE

Ini lebih baik daripada readlink -e FILEatau realpath, karena berfungsi bahkan jika file tidak ada.

Flimm
sumber
Bagus. Ini juga berfungsi pada file / direktori yang memang ada tetapi bukan symlink.
quietmint
Saya memiliki tautan baca yang tersedia di OS X 10.9 (Mavericks), jadi ini pasti jawaban terbaik di sini.
Kenneth Hoste
6
@KennethHoste: -mopsi ini tidak tersedia di Mavericks.
iconoclast
2
Jelas itu bukan pada instalasi DEFAULT OSX.
Fran Marzoa
berfungsi di linux (CentOS) terima kasih, karena realpath tidak ada untuk itu
jimh
65

Jalur relatif ini ke fungsi shell konverter jalur absolut

  • tidak memerlukan utilitas (adil cddan pwd)
  • berfungsi untuk direktori dan file
  • menangani ..dan.
  • menangani spasi dalam dir atau nama file
  • mengharuskan file atau direktori ada
  • mengembalikan apa-apa jika tidak ada yang ada di jalur yang diberikan
  • menangani path absolut sebagai input (melewati mereka pada dasarnya)

Kode:

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
}

Sampel:

# 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

Catatan: Ini didasarkan pada jawaban dari nolan6000 dan bsingh , tetapi memperbaiki kasus file.

Saya juga mengerti bahwa pertanyaan awal adalah tentang utilitas baris perintah yang ada. Tapi karena ini sepertinya pertanyaan THE pada stackoverflow untuk itu termasuk skrip shell yang ingin memiliki dependensi minimal, saya meletakkan solusi skrip ini di sini, jadi saya bisa menemukannya nanti :)

Alexander Klimetschek
sumber
Terima kasih. Itulah yang saya lakukan dengan OSX
Greg
Ini tidak berfungsi untuk direktori dengan spasi, yaitu: $ abspath 'a b c/file.txt'Itu karena argumen untuk cdtidak dikutip. Untuk mengatasi ini, alih-alih mengutip seluruh argumen untuk echo(adakah alasan untuk kutipan ini?) Hanya mengutip argumen path. Yaitu ganti echo "$(cd ${1%/*}; pwd)/${1##*/}"dengan echo $(cd "${1%/*}"; pwd)/${1##*/}.
george
@george Terima kasih telah mencatat, saya memperbaikinya.
Alexander Klimetschek
1
Saya melihat melalui lusinan solusi setengah-cocked dan ini tampaknya menjadi solusi bash-only yang paling singkat dan akurat. Anda dapat melangsingkannya lebih banyak dengan menggantinya echo "$(cd "$1"; pwd)"dengan (cd "$1"; pwd). Tidak perlu gema di sini.
Enam
@ Enam Benar, diperbarui. Kawat gigi ( ... )masih diperlukan, jadi itu cdterjadi dalam subkulit, karena kami tidak ingin mengubah direktori kerja untuk pemanggil abspath.
Alexander Klimetschek
24

The findperintah dapat membantu

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

Daftar semua file di atau di bawah direktori saat ini dengan nama yang cocok dengan polanya. Anda dapat menyederhanakannya jika Anda hanya akan mendapatkan beberapa hasil (misalnya direktori di dekat bagian bawah pohon yang berisi beberapa file), adil

find $PWD

Saya menggunakan ini pada Solaris 10, yang tidak memiliki utilitas lain yang disebutkan.

lessthanideal
sumber
1
saya tidak grok komentar ini pada bacaan pertama; titik kunci di sini adalah bahwa jika Anda memberikan path absolut ke perintah find maka akan menghasilkan hasil di path absolut. jadi menggunakan $ PWD adalah jalur absolut dari tempat Anda berada sehingga Anda mendapatkan output sebagai absolut.
simbo1905
4
Jika Anda mengandalkan PWD, Anda bisa menggunakannya $PWD/$filename.
Jonny
Pendekatan ini dapat ditingkatkan dengan menggunakan -maxdepth 1. Juga jangan lupa tentang mengutip - masalah keamanan potensial di sini, tergantung bagaimana Anda menggunakannya.
mc0e
1
@jonny: $ PWD / $ nama file gagal jika $ nama file sudah absolut.
mc0e
Ini gagal jika nama file diberikan sebagai "./filename.txt" (dengan titik awal dan garis miring).
Mark Stosberg
15

Jika Anda tidak memiliki utilitas readlink atau realpath daripada Anda dapat menggunakan fungsi berikut yang bekerja di bash dan zsh (tidak yakin tentang yang lain).

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

Ini juga berfungsi untuk file yang tidak ada (seperti halnya fungsi python os.path.abspath).

Sayangnya abspath ./../somefiletidak menghilangkan titik-titik.

hluk
sumber
1
Terlihat portabel untuk saya. Di sisi lain, akan pecah misalnya pada nama file yang mengandung baris baru.
Roman Cheplyaka
1
Untuk meningkatkan lebih lanjut, ganti echo "$1"dengan printf "%s\n" "$1"(sama dengan gema kedua). echodapat menafsirkan garis miring terbalik di dalam argumennya.
Roman Cheplyaka
Sekali lagi, Anda benar! Sungguh, perilaku perintah echo di zsh berbeda dari bash.
hluk
1
Tegasnya, di bawah POSIX perilaku echo tidak terdefinisi jika argumen mengandung garis miring terbalik. Namun, itu didefinisikan di bawah ekstensi XSI (yaitu, gema harus menafsirkan urutan melarikan diri). Tetapi baik bash dan zsh bahkan sangat jauh dari kepatuhan POSIX ...
Roman Cheplyaka
Maaf, tapi saya tidak mengerti intinya. Saya sudah memberikan jawaban sebagai skrip dengan lebih banyak fitur yang ini dan itu tidak perlu digunakan dalam skrip shell.
dhardy
10

Berikut ini adalah fungsi zsh-only yang saya sukai karena kekompakannya. Ia menggunakan pengubah ekspansi 'A' - lihat zshexpn (1).

realpath() { for f in "$@"; do echo ${f}(:A); done }
wjv
sumber
Wow itu solusi yang elegan !!
ShellFish
6

Ada hal umumnya tidak ada seperti yang absolute path ke file (pernyataan ini berarti bahwa mungkin ada lebih dari satu pada umumnya, maka penggunaan artikel yang pasti yang tidak tepat). An absolute pathadalah setiap jalur yang dimulai dari root "/" dan menunjuk file tanpa ambiguitas secara independen dari direktori kerja. (Lihat misalnya wikipedia ).

A relative pathadalah jalur yang harus ditafsirkan mulai dari direktori lain. Ini mungkin direktori kerja jika relative pathsedang dimanipulasi oleh aplikasi (meskipun tidak harus). Ketika berada di tautan simbolis dalam direktori, umumnya dimaksudkan untuk relatif terhadap direktori itu (meskipun pengguna mungkin memiliki kegunaan lain dalam pikiran).

Karenanya path absolut hanyalah path relatif ke direktori root.

Jalur (absolut atau relatif) mungkin mengandung atau tidak mengandung tautan simbolik. Jika tidak, itu juga agak tahan terhadap perubahan dalam struktur yang menghubungkan, tetapi ini tidak selalu diperlukan atau bahkan diinginkan. Beberapa orang memanggil canonical path(atau canonical file nameatau resolved path) suatu absolute pathdi mana semua tautan simbolik telah dipecahkan, yaitu telah diganti oleh jalur ke mana pun tautan itu. Perintah realpathdan readlinkkeduanya mencari jalur kanonik, tetapi hanya realpathmemiliki opsi untuk mendapatkan jalur absolut tanpa repot-repot menyelesaikan tautan simbolik (bersama dengan beberapa opsi lain untuk mendapatkan berbagai jenis jalur, absolut atau relatif ke beberapa direktori).

Ini membutuhkan beberapa komentar:

  1. tautan simbolik hanya dapat diselesaikan jika apa pun yang seharusnya mereka tautkan sudah dibuat, yang jelas tidak selalu demikian. Perintah realpathdan readlinkmemiliki opsi untuk menjelaskannya.
  2. direktori pada jalur nantinya bisa menjadi tautan simbolik, yang berarti jalur itu tidak lagi canonical. Karenanya konsep ini bergantung pada waktu (atau lingkungan).
  3. bahkan dalam kasus yang ideal, ketika semua tautan simbolis dapat diselesaikan, mungkin masih ada lebih dari satu canonical pathke file, karena dua alasan:
    • partisi yang berisi file mungkin telah dipasang secara bersamaan ( ro) pada beberapa titik pemasangan.
    • mungkin ada tautan keras ke file tersebut, artinya pada dasarnya file tersebut ada di beberapa direktori berbeda.

Oleh karena itu, bahkan dengan definisi yang jauh lebih ketat canonical path, mungkin ada beberapa jalur kanonik ke file. Ini juga berarti bahwa kualifikasi canonicalagak tidak memadai karena biasanya menyiratkan gagasan tentang keunikan.

Ini memperluas diskusi singkat tentang topik dalam jawaban untuk pertanyaan serupa lainnya di Bash: mengambil jalur absolut yang diberikan relatif

Kesimpulan saya adalah yang realpathdirancang lebih baik dan jauh lebih fleksibel daripada readlink. Satu-satunya penggunaan readlinkyang tidak tercakup realpathadalah panggilan tanpa opsi mengembalikan nilai tautan simbolik.

babou
sumber
Saya tidak keberatan direndahkan, tetapi saya suka memahami mengapa sehingga saya dapat mempelajari sesuatu, baik teknis atau mengenai apa yang dianggap praktik yang tepat di situs. Yah ... setidaknya itu mendorong saya untuk mendaftar dengan Meta Stack Overflow untuk lebih memahami sosiologi lokal. Saya merekomendasikannya. - Namun, jika ada yang punya pendapat tentang ketidakcocokan jawaban saya, saya tertarik.
babou
1
(a) pertanyaan memiliki jawaban yang valid dari 2 + 1/2 tahun yang lalu, (b) ada jalur absolut (tunggal) yang sesuai dengan jalur relatif (yang saya inginkan), meskipun mungkin tidak ke file seperti Anda ditunjukkan. BTW komentar apa pun tentang realpathvs readlinkatau bahkan tentang tautan simbolis adalah surplus untuk apa yang saya minta.
dhardy
1
Komentar kedua: jawaban singkat seringkali lebih bermanfaat daripada kuliah panjang. Stack overflow biasanya digunakan untuk mengajukan pertanyaan spesifik.
dhardy
5
1- fakta bahwa suatu pertanyaan telah memiliki jawaban yang valid untuk waktu yang lama tidak berarti bahwa pertanyaan itu sudah ditutup. Pertanyaan-pertanyaan ini tidak dimaksudkan untuk penggunaan pribadi saja. Memang, ada lencana untuk balasan yang mengumpulkan lebih banyak suara daripada jawaban yang divalidasi. Dan dengan alat baru, jawaban "terbaik" dapat berubah seiring waktu. Banyak orang menggunakan jawaban lama yang diakses melalui pencarian web.
babou
1
2 - Anda bersikeras bahwa ada jalur absolut (tunggal) yang sesuai dengan jalur relatif . Sementara saya menebak apa yang Anda maksud dengan "korespondensi", yaitu jalur yang berasal dari aslinya melalui serangkaian transformasi yang diberikan, pernyataan Anda masih salah. Ada jalur kanonik "korespondensi" yang unik. Kata ini canonicalmerujuk tepatnya pada keunikan ini relatif terhadap serangkaian transformasi. Tetapi, misalnya, / dev / cdrom adalah path absolut yang sangat bagus, meskipun sebenarnya itu adalah tautan ke / dev / sr0. Keduanya menunjuk ke perangkat yang sama. Jawaban asli saya menunjuk ke artikel web yang relevan.
babou
5

The dogbane jawabannya dengan deskripsi apa yang menimpa:

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

Penjelasan:

  1. Script ini mendapatkan path relatif sebagai argumen "$1"
  2. Kemudian kita mendapatkan bagian dirname dari jalur itu (Anda bisa mengirimkan dir atau file ke skrip ini):dirname "$1"
  3. Lalu kita cd "$(dirname "$1")ke dir relatif ini dan mendapatkan path absolut untuk itu dengan menjalankan pwdperintah shell
  4. Setelah itu kita tambahkan nama samaran ke path absolut:$(basename "$1")
  5. Sebagai langkah terakhir kita echoitu
Eugen Konkov
sumber
2

Untuk direktori dirnametersandung ../dan kembali ./.

Fungsi nolan6000 dapat dimodifikasi untuk memperbaikinya:

get_abs_filename() {
  # $1 : relative filename
  if [ -d "${1%/*}" ]; then
    echo "$(cd ${1%/*}; pwd)/${1##*/}"
  fi
}
bsingh
sumber
1
Selamat datang di SO! Untuk perubahan dan komentar kecil, menambahkan komentar ke jawaban yang ada mungkin lebih tepat daripada menambahkan jawaban, terutama jika jawaban yang disalin ini tidak memiliki banyak informasi lain dari jawaban asli. Setelah mengumpulkan sedikit lebih banyak reputasi, Anda dapat menambahkan komentar ke jawaban orang lain. Untuk saat ini, cobalah untuk mengumpulkan reputasi dengan mengajukan pertanyaan unik dan berharga atau memberikan jawaban yang baik dan berdiri sendiri.
cfi
1
Karena Anda merujuk pada jawaban nolan6000, harap dicatat bahwa poster dhardy sudah berkomentar bahwa ia tidak akan menerima jawaban nolan6000 karena ia tidak mencari skrip. Jadi, sebenarnya jawaban Anda tidak menjawab pertanyaan.
cfi
fungsi dapat ditambahkan ke .profiledan karenanya tersedia untuk penggunaan interaktif.
adib
Ini tidak akan berfungsi jika $1nama file polos: get_abs_filename foo-> tidak ada (atau <current_dir>/foo/foojika foodirektori).
ivan_pozdeev
2

Ini bukan jawaban untuk pertanyaan, tetapi bagi mereka yang menulis:

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

ia menangani / ... ... dll dengan benar. Saya juga tampaknya bekerja di OSX

Alek
sumber
2

Saya telah menempatkan skrip berikut pada sistem saya & saya menyebutnya sebagai bash alias ketika saya ingin dengan cepat mengambil path lengkap ke file di dir saat ini:

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

Saya tidak yakin mengapa, tetapi, pada OS X ketika dipanggil oleh skrip "$ PWD" meluas ke jalur absolut. Ketika perintah find dipanggil pada baris perintah, itu tidak. Tapi itu melakukan apa yang saya inginkan ... nikmati.

fred.johnsen
sumber
$PWDselalu memiliki jalur absolut direktori kerja. Juga, findtidak akan mentolerir garis miring, jadi Anda tidak menjawab pertanyaan seperti yang diajukan. Cara yang lebih cepat untuk melakukan apa yang Anda ingin lakukan hanyalahecho "$PWD/$1"
Adam Katz
2

Yang paling sederhana jika Anda hanya ingin menggunakan builtin adalah:

find `pwd` -name fileName

Hanya dua kata tambahan untuk diketik, dan ini akan bekerja pada semua sistem unix, serta OSX.

Arj
sumber
Saya akan menambahkan -maxdepth 1sebelumnya -name(seandainya file ada di direktori saat ini). Tanpa itu ia akan bekerja dengan file di subdirektori pwd, tetapi tidak dengan yang lain.
Walter Tross
Memang Anda benar, pertanyaannya memang menentukan bahwa file tersebut akan berada di direktori saat ini. Apa maksudmu "tetapi tidak dengan orang lain"?
Arj
Maksud saya findtidak akan menemukan file di luar pohon direktori di bawahnya pwd. Misalnya, jika Anda mencoba find . -name ../existingFile, itu gagal.
Walter Tross
Cukup adil, ya ini akan menganggap Anda ingin mencetak path lengkap file di cwd Anda (sesuai pertanyaan asli), atau di mana saja di pohon cwd Anda (bukan dalam pertanyaan asli).
Arj
1
#! /bin/bash

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

Ini menebus kekurangan realpath, menyimpannya dalam skrip shell fullpath. Anda sekarang dapat menelepon:

$ 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.
Kerang
sumber
Apa yang dipecahkannya? realpath "foo bar"-> /home/myname/foo bar. Jika Anda tidak dapat repot mengutip argumen baris perintah, itu bukan realpathsalah.
ivan_pozdeev
Setuju, ini lebih merupakan pembungkus kenyamanan.
ShellFish
1

Alternatif untuk mendapatkan path absolut di Ruby :

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

Bekerja tanpa argumen (folder saat ini) dan path file atau folder relatif dan absolut sebagai agumen.

Atika
sumber
0

Jawab dengan Homebrew

realpathadalah jawaban terbaik, tetapi jika Anda belum menginstalnya, Anda harus terlebih dahulu menjalankan brew install coreutilsyang akan menginstal coreutils dengan banyak fungsi luar biasa. Menulis fungsi khusus dan mengekspornya terlalu banyak pekerjaan dan berisiko kesalahan untuk sesuatu seperti ini, berikut adalah dua baris:

$ brew install coreutils
$ realpath your-file-name.json 
Zorayr
sumber
-1

Hai teman-teman, saya tahu ini adalah utas lama tetapi saya hanya memposting ini untuk referensi kepada orang lain yang mengunjungi ini seperti saya. Jika saya mengerti pertanyaan dengan benar, saya pikir locate $filenameperintahnya. Ini menampilkan jalur absolut dari file yang disediakan, tetapi hanya jika ada.

icyyd
sumber
4
locateadalah utilitas untuk mencari file / jalur dengan nama. Mungkin melakukan pekerjaan tetapi juga dapat menemukan kecocokan lain dan mungkin tidak menemukan file yang ada tanpa memanggil updatedbsebagai root terlebih dahulu.
dhardy