web-dev-qa-db-fra.com

Lire le fichier distant commençant par "smb: //" en utilisant R

Pour lire un fichier dans R, je ferais normalement quelque chose comme ceci:

read.csv('/Users/myusername/myfilename.csv')

Mais j'essaie de lire un fichier situé sur un serveur distant (partage Windows SMB/CIFS) auquel j'accède sur mon Mac via le FinderGo → - Se connecter au serveur élément de menu.

Quand je vois les propriétés du fichier that, le chemin du fichier est différent de celui auquel je suis habitué. Au lieu de commencer par: /Users/myusername/..., il est smb://server.msu.edu/.../myfilename.csv.

En essayant de lire le fichier, j'ai essayé ce qui suit:

read.csv('smb://server.msu.edu/.../myfilename.csv')

Mais cela n'a pas fonctionné.

Au lieu de l'erreur habituelle "Aucun fichier ou répertoire", cela a renvoyé:

smb: //server.msu.edu/.../myfilename.csv n'existe pas dans le répertoire de travail actuel

J'imagine que le chemin du fichier a besoin d'un format différent, mais je ne sais pas quoi.

Comment lire ce type de fichier dans R?

20
Joshua Rosenberg

Explication

smb://educ-srvmedia1.campusad.msu.edu/... Est en fait une URL et non un chemin de fichier.

Décomposons cela

smb:// Signifie utiliser le protocole de bloc de messages du serveur (partage de fichiers)

educ-srvmedia1.campusad.msu.edu Est le nom du serveur

/.../myfilename.csv Est le partage/chemin du fichier sur le serveur distant

Vous pouvez accéder à ce répertoire à l'aide du Finder sur OSX car il prend en charge le protocole SMB. Finder se connecte au service distant à l'aide de l'URL et vous permet de parcourir les fichiers.

Cependant, R ne comprend pas le protocole SMB donc ne peut pas interpréter correctement le chemin du fichier.

La fonction Rread.csv() utilise file() en interne, voir https://stat.ethz.ch/R-manual/R-devel/library/ base/html/connections.html

url et fichier prennent en charge les schémas d'URL: //, http: //, https: // et ftp: //

Par conséquent, R renvoie le message "impossible de localiser le fichier" car le fichier est introuvable car le protocole n'est pas pris en charge. oui, un peu déroutant.

Réparer

Vous devez monter le partage de fichiers sur votre système de fichiers local.

Tout cela signifie que les détails du protocole SMB seront gérés en arrière-plan par le système d'exploitation et le partage de fichiers sera présenté comme un répertoire local.

Cela permettra à R (et à d'autres programmes) de traiter les fichiers distants à toutes fins utiles, comme tout autre fichier local. Cette discussion montre quelques options pour le faire.

par exemple.

# need to create /LocalFolder first
mount -t cifs //username:password@hostname/sharename /LocalFolder

puis en R:

read.csv('/LocalFolder/myfilename.csv')

Supplémentaire

Les utilisateurs de Windows peuvent accomplir cela plus facilement avec les chemins UNC
Comment lire des fichiers à partir d'un répertoire spécifié par UNC dans R?

18
stacksonstacks

TL; DR

Voici une approche portable qui utilise cURL et ne nécessite pas de monter des systèmes de fichiers distants:

> install.packages("curl")
> require("curl")
> handle <- new_handle()
> handle_setopt(handle, username = "domain\\username")
> handle_setopt(handle, password = "secret") # If needed
> request <- curl_fetch_memory("smb://Host.example.com/share/file.txt", handle = handle)
> contents <- rawToChar(request$content)

Si nous devons lire le contenu au format CSV, comme dans la question, nous pouvons diffuser le fichier via une autre fonction:

> stream <- curl("smb://Host.example.com/share/file.txt", handle = handle)
> contents <- read.csv(stream)

Jetons un œil à un moyen plus robuste d'accéder aux fichiers distants via les URL smb: // en plus de l'approche décrite dans d'autres réponses qui monte le système de fichiers distant. Malheureusement, je suis un peu en retard pour celui-ci, mais j'espère que cela aidera les futurs lecteurs.

Dans certains cas, nous ne pouvons pas avoir les privilèges nécessaires pour monter un système de fichiers (cela nécessite un accès administrateur ou root sur de nombreux systèmes), ou nous pouvons tout simplement pas voulez pour monter un système de fichiers entier juste pour lire un seul fichier. Nous utiliserons la bibliothèque cURL pour lire le fichier à la place. Cette approche améliore la flexibilité et la portabilité de nos programmes car nous n'avons pas besoin de dépendre de l'existence d'un système de fichiers monté en externe. Nous allons examiner deux manières différentes: via un appel system(), et en utilisant un package qui fournit une API cURL.

Quelques informations: pour ceux qui ne le connaissent pas, cURL fournit des outils utilisés pour transférer des données via différents protocoles. Depuis version 7.40 , cURL prend en charge le protocole SMB/CIFS généralement utilisé pour les services de partage de fichiers Windows. cURL inclut n outil en ligne de commande que nous pouvons utiliser pour récupérer le contenu d'un fichier:

$ curl -u 'domain\username' 'smb://Host.example.com/share/file.txt'

La commande ci-dessus lit et sort (vers STDOUT) le contenu de file.txt depuis le serveur distant Host.example.com authentification en tant qu'utilisateur spécifié sur le domaine. La commande nous demandera un mot de passe si nécessaire. Nous pouvons supprimer la partie domaine du nom d'utilisateur si notre réseau n'utilise pas de domaine.

Appel système

Nous pouvons obtenir la même fonctionnalité dans R en utilisant la fonction system() :

system("curl -u 'domain\\username' 'smb://Host.example.com/share/file.txt'")

Notez la double barre oblique inverse dans domain\\username. Cela échappe le caractère barre oblique inverse afin que R ne l'interprète pas comme un caractère d'échappement dans la chaîne. Nous pouvons capturer le contenu du fichier de la sortie de la commande dans une variable en définissant le paramètre intern de la fonction system() sur TRUE:

contents <- system("curl -u 'domain\\username' 'smb://Host.example.com/share/file.txt'", intern = TRUE)

... ou en appelant system2() à la place, qui cite les arguments de commande pour la sécurité et gère mieux la redirection de processus entre les plates-formes:

contents <- system2('curl', c("-u", "domain\\\\username", "smb://Host.example.com/share/file.txt"), stdout = TRUE)

Le curl La commande nous demandera toujours un mot de passe si requis par le serveur distant. Alors que nous pouvons spécifier un mot de passe en utilisant -u 'domain\\username:password' Pour éviter l'invite, cela expose le mot de passe en texte brut dans la chaîne de commande. Pour une approche plus sécurisée, lisez la section ci-dessous qui décrit l'utilisation d'un package.

Nous pouvons également ajouter le drapeau -s Ou --silent Au curl pour supprimer la sortie d'état de progression. Notez que cela masquera également les messages d'erreur, nous pouvons donc également vouloir ajouter -S (--show-error). La variable contents contiendra un vecteur des lignes du fichier — similaire à la valeur renvoyée par readLines("file.txt")— que nous pouvons recréer ensemble en utilisant paste(contents, collapse = "\n").

API cURL

Bien que tout fonctionne bien, nous pouvons améliorer cette approche en utilisant une bibliothèque cURL dédiée. Ce paquet curl fournit des liaisons R à libcurl afin que nous puissions utiliser directement l'API cURL dans notre programme. Nous devons d'abord installer le package:

install.packages("curl")
require("curl")

(Les utilisateurs Linux devront installer les fichiers de développement libcurl .)

Ensuite, nous pouvons lire le fichier distant dans une variable en utilisant la fonction curl_fetch_memory():

handle <- new_handle()
handle_setopt(handle, username = "domain\\username")
handle_setopt(handle, password = "secret") # If needed
request <- curl_fetch_memory("smb://Host.example.com/share/file.txt", handle = handle)
content <- rawToChar(request$content)

Nous créons d'abord un handle pour configurer la demande en définissant les options d'authentification nécessaires. Ensuite, nous exécutons la demande et assignons le contenu du fichier à une variable. Comme indiqué, définissez le password CURLOPT si nécessaire.

Pour traiter un fichier distant comme nous le ferions avec read.csv(), nous devons créer une connexion de streaming. La fonction curl() crée un objet de connexion que nous pouvons utiliser pour diffuser le contenu du fichier via n'importe quelle fonction qui prend en charge un argument renvoyé par la fonction standard url(). Par exemple, voici un moyen de lire le fichier distant au format CSV, comme dans la question:

handle = new_handle()
...
stream <- curl("smb://Host.example.com/share/file.txt", handle = handle)
contents <- read.csv(stream)

Bien sûr, les concepts décrits ci-dessus s'appliquent à la récupération du contenu ou du corps de réponse sur n'importe quel protocole pris en charge par cURL, pas seulement SMB/CIFS. Si nécessaire, nous pouvons également utiliser ces outils pour télécharger des fichiers dans le système de fichiers au lieu de simplement lire le contenu en mémoire.

10
Cy Rossignol

Ci-dessous, j'ai montré un moyen que j'ai utilisé de temps en temps pour lire les données d'un lecteur réseau SMB. Dans le code ci-dessous, j'ai utilisé le R system fonction pour tout faire à partir de R, mais vous pouvez également monter le lecteur à partir de la ligne de commande OSX ou à partir du Finder avec Command-K (connexion au serveur):

Si vous n'en avez pas déjà un, créez un répertoire sur votre lecteur local où le partage sera situé (ce n'est pas nécessaire, car vous pouvez monter le lecteur dans un emplacement existant):

system("mkdir /Users/eipi10/temp_share/")

ou

dir.create("/Users/eipi10/temp_share/")

Montez le lecteur réseau dans le dossier que vous venez de créer. Dans le code ci-dessous, //[email protected]/home/u/eipi10 est votre nom d'utilisateur et l'adresse du partage SMB.

system("mount_smbfs //[email protected]/home/u/eipi10 /Users/eipi10/temp_share")

S'il y a authentification par mot de passe, le mot de passe peut également être inclus:

system("mount_smbfs //username:[email protected]/home/u/eipi10 /Users/eipi10/temp_share")

Lisez les données:

dat = read.csv("/Users/eipi10/temp_share/fileToRead.csv")

Dans R, vous pouvez également sélectionner par programme les fichiers à lire:

data.list = lapply(list.files(pattern="csv$", "/Users/eipi10/temp_share/", full.names=TRUE), read.csv)
5
eipi10

SMB est le protocole de dossier réseau Windows.

Des cas similaires incluent sftp:// URL, par exemple.

Vous pouvez soit:

  1. montez le dossier dans votre système d'exploitation et accédez-y en utilisant un chemin normal,
  2. utiliser une bibliothèque de système de fichiers virtuel, telle que GVFS/GIO sous Linux. Peut-être qu'il existe un wrapper R autour de cela que vous pouvez utiliser.
1
Anony-Mousse

À mon avis, il existe deux façons d'atteindre votre objectif.

  • La première consiste à utiliser fstab pour ajouter définitivement le dossier distant comme disque local.

  • La seconde consiste à monter temporairement le dossier distant comme un dossier quand il est nécessaire


Ci-dessous, je vais expliquer comment la deuxième méthode peut être mise en œuvre

  • Créez un répertoire local:

    mkdir <mountdirectory>

  • Montez votre répertoire distant sur le local avec cette ligne de commande:

    sshfs <remoteserverip>:<remotedirpath> <mountdirectory>pour SSH

    OU (installez d'abord les cifs: Sudo apt-get install cifs-utils)

    mount -t cifs -o username=<USERNAME>,password=<PASSWD> //<remoteserverip>/<remotedirpath> <mountdirectory>pour SMB

  • Faites le travail avec le fichier local !

  • À la fin, utilisez cette commande pour démonter:

    fusermount -u <mountdirectory>

0
A STEFANI