2013-07-04 13 views
17

Próbuję uruchomić mplayer. Moja nazwa pliku zawiera spacje i powinny one zostać zmienione. Jest to kod używam:Jak uciec ciągi dla terminala w Ruby?

@player_pid = fork do 
    exec "/usr/bin/mplayer #{song.file}" 
end 

gdzie #{song.file} zawiera ścieżkę jak "/home/example/music/01 - a song.mp3". Jak mogę właściwie uciec tej zmiennej (i ewentualnych innych dziwnych znaków, które tytuł może zawierać), aby terminal zaakceptował moje polecenie?

Odpowiedz

29

Shellwords powinny pracować dla Ciebie :)

exec "/usr/bin/mplayer %s" % Shellwords.escape(song.file) 

w Ruby 1.9.x, wygląda na to trzeba require najpierw

require "shellwords" 

Ale w Ruby 2.0.x, Nie musiałem tego wyraźnie wymagać.

+0

Dzięki, że działa! – xorinzor

15

Proszę nigdy nie używać "pojedynczej linii poleceń" z formularza exec, która pozostawia otwarte dla wszystkich zwykłych problemów z cytowaniem i wstrzykiwaniem i bezcelowo uruchamia powłokę. Z fine manual:

exec (cmdname, arg1, ...)

nazwy poleceń i jeden lub więcej argumentów (bez powłoki)

więc zamiast mucking z cytowania i uciekając, a co nie, po prostu użyj wersji bez powłoki:

exec '/usr/bin/mplayer', song.file 

i obejść powłokę etely. Podobnie dla system.

+1

Trudnością będzie to, że nie każdy ma ścieżkę '/ usr/bin/mplayer', więc być może trzeba będzie odwołać się do mechanizmu, aby zlokalizować plik wykonywalny. Oczywiście, jeśli ten program jest tylko do twojej konsumpcji, powinno być dobrze. – vgoff

+0

To rozwiązanie działa również, ale ponieważ moje pytanie dotyczyło ucieczki z łańcucha, zamierzam pozostawić odpowiedź bez zmian, dziękuję. – xorinzor

+0

@vgoff: Wiesz, że 'exec' przeszuka' PATH', prawda? A jeśli spróbujesz użyć '/ usr/bin/mplayer' z dowolną formą' exec', a nie masz 'mplayer' w'/usr/bin', to oczywiście nie uda się to w obu przypadkach. –