Jak sprawdzić, czy katalog / plik / dowiązanie symboliczne istnieje z jednym poleceniem w Rubim

83

Czy istnieje jeden sposób na wykrycie, czy katalog / plik / dowiązanie symboliczne / etc? istota (bardziej uogólniona) istnieje?

Potrzebuję jednej funkcji, ponieważ muszę sprawdzić tablicę ścieżek, które mogą być katalogami, plikami lub dowiązaniami symbolicznymi. Wiem, że File.exists?"file_path"działa dla katalogów i plików, ale nie dla linków symbolicznych (co jest File.symlink?"symlink_path").

claudiut
źródło
1
Jakiej wersji Rubiego używasz? Plik istnieje? działa dla mnie dla linków symbolicznych w Ruby 1.9.2 w OS X 10.6.6
1
Dla wyjaśnienia: w przypadku dowiązań symbolicznych pytasz o coś, co zwraca, truejeśli dowiązanie symboliczne istnieje, niezależnie od tego, czy ostatecznie można je przekształcić w nie dowiązanie symboliczne. Oznacza to, że powinien powrócić również w trueprzypadku uszkodzonych linków. File.exists?zwróci tylko truedla łącza symbolicznego, które nie jest uszkodzone.
Kelvin

Odpowiedzi:

147

Standardowy moduł plików ma dostępne zwykłe testy plików :

RUBY_VERSION # => "1.9.2"
bashrc = ENV['HOME'] + '/.bashrc'
File.exist?(bashrc) # => true
File.file?(bashrc)  # => true
File.directory?(bashrc) # => false

Powinieneś być w stanie znaleźć tam to, czego chcesz.


OP: „Dziękuję, ale potrzebuję wszystkich trzech prawdy lub fałszu”

Oczywiście, że nie. Ok, spróbuj czegoś takiego:

def file_dir_or_symlink_exists?(path_to_file)
  File.exist?(path_to_file) || File.symlink?(path_to_file)
end

file_dir_or_symlink_exists?(bashrc)                            # => true
file_dir_or_symlink_exists?('/Users')                          # => true
file_dir_or_symlink_exists?('/usr/bin/ruby')                   # => true
file_dir_or_symlink_exists?('some/bogus/path/to/a/black/hole') # => false
Blaszany Człowiek
źródło
1
Odradzałbym konkatenację nieprzetworzonych ciągów znaków ( ENV['HOME'] + '/.bashrc'), co może nie działać na wielu platformach. Powinieneś użyć złączeń Ruby File i dlaczego nie zacząć od tego, Rails.rootjeśli używasz Railsów. File.exists?(Rails.root.join('db', 'my_seeds.csv')
Cyril Duchon-Doris
2
Gwarantuje się, że nie będzie działać na wielu platformach, ponieważ system Windows nie wie o Bash, a zatem o .bashrc. Ale działałoby na platformie opartej na * nix. Użycie /nie jest jednak problemem, ponieważ IO Rubiego automatycznie konwertuje z ukośników w przód na ukośniki w systemie Windows .
Tin Man
Może to prawda w grudniu 2016, ale Windows pewno nie wie o Bash te dni. :-) Mogę pisać bashw menu Start, aw wynikowym oknie konsoli cat ~/.bashrcgeneruje dane wyjściowe. ¯ \ _ (ツ) _ / ¯
Jonathan Gilbert
Odpowiedź Cyrila nie jest niestety w pełni poprawna - konkatenacja ciągów CZY działa w systemie Windows dla "File.exist?" czeki, jak już wskazał Blaszany Człowiek. Dodałem ten komentarz tylko po to, aby to potwierdzić.
shevy
14

Dlaczego nie zdefiniować własnej funkcji File.exists?(path) or File.symlink?(path)i jej nie wykorzystać?

Gintautas Miliauskas
źródło
2
@Clawsy Myślę, że brakuje ci punktu Gintautasa: jesteś programistą - jeśli funkcja, której potrzebujesz, nie istnieje, możesz ją stworzyć.
Telemachus
4
Po co wymyślać koło na nowo, skoro jest już częścią języka?
Tin Man
11
Uważam, że bardzo przydatne jest unikanie zbytniej obsesji na punkcie szczegółów w programowaniu. Jeśli znasz prosty i prosty sposób rozwiązania problemu, zrób to. Jeśli jakiś czas później znajdziesz lepszy sposób, zawsze możesz wrócić i naprawić. Zdefiniowanie nowej funkcji jest w tej sytuacji oczywiste.
Gintautas Miliauskas
5
Ale ta funkcjonalność jest już wbudowana w język i jest prosta w użyciu. Następnie trzeba przeczytać, co jest dostępne, i dodać wezwanie. Pisanie kodu w celu zaimplementowania funkcjonalności, która już istnieje, tylko dlatego, że nie poświęciłeś czasu na przeczytanie RDoc, który jest dostarczany z językiem ... po prostu mi nie pasuje. Zgodnie z tą logiką możesz skończyć przepisując standardową bibliotekę.
Tin Man,
2
Użyj File.exist? zamiast File.exists? ponieważ jest to przestarzałe w Ruby 2.2.0: ruby-doc.org/core-2.2.0/File.html#method-c-exists-3F
atw