OVH Cloud OVH Cloud

Fonctionnement de EXEC ('master..xp_cmdshell ' + @OS_COMMANDE)

5 réponses
Avatar
Arnaud CAVELIER
Bonjour,

Il y a quelques temps Fred Brouard m'a proposé une procédure pour récupérer
le nom des fichiers d'un répertoire donné.

Cela a bien fonctionné jusqu'au jour où j'ai changé d'OS (ce matin en
l'occurence).

A priori, la structure de la LINE diffère d'un Windows XP Français à un
Windows 2003 Server Américain.

Est-il possible d'avoir une info plus précise sur le contenu de cette LINE ?
Ou comment être certain de la position du nom de fichier dans la chaine ?

Merci
Arnaud

"Fred BROUARD" wrote:

> Un petit exemple :
>
> DECLARE @OS_COMMANDE NVARCHAR(4000)
> SET @OS_COMMANDE = '''DIR C:\*.txt'''
>
> CREATE TABLE #dir (line NVARCHAR(256))
>
> INSERT INTO #dir
> EXEC ('master..xp_cmdshell ' + @OS_COMMANDE)
>
> DELETE FROM #dir
> WHERE line IS NULL
>
> DELETE FROM #dir
> WHERE SUBSTRING(line, 1, 1) = ' '
>
> SELECT *
> FROM #dir
>
> A +

5 réponses

Avatar
Patrice
"dir c:*.txt /b" devrait permettre de n'avoir que les noms...

--

"Arnaud CAVELIER" a écrit dans le
message de news:
Bonjour,

Il y a quelques temps Fred Brouard m'a proposé une procédure pour


récupérer
le nom des fichiers d'un répertoire donné.

Cela a bien fonctionné jusqu'au jour où j'ai changé d'OS (ce matin en
l'occurence).

A priori, la structure de la LINE diffère d'un Windows XP Français à un
Windows 2003 Server Américain.

Est-il possible d'avoir une info plus précise sur le contenu de cette LINE


?
Ou comment être certain de la position du nom de fichier dans la chaine ?

Merci
Arnaud

"Fred BROUARD" wrote:

> Un petit exemple :
>
> DECLARE @OS_COMMANDE NVARCHAR(4000)
> SET @OS_COMMANDE = '''DIR C:*.txt'''
>
> CREATE TABLE #dir (line NVARCHAR(256))
>
> INSERT INTO #dir
> EXEC ('master..xp_cmdshell ' + @OS_COMMANDE)
>
> DELETE FROM #dir
> WHERE line IS NULL
>
> DELETE FROM #dir
> WHERE SUBSTRING(line, 1, 1) = ' '
>
> SELECT *
> FROM #dir
>
> A +



Avatar
GNocent
Salut,

Une solution pour le rencensement de fichiers d'un répertoire est de
modifier ton dir pour lui faire renvoyer des lignes plus simples à parser
(mais tu perds les infos sur la date et la taille) :

-- =============================================
DECLARE @CMD NVARCHAR(200)

SELECT @CMD = 'DIR /B /A-D C:*.txt'

CREATE TABLE #dir (line NVARCHAR(500))

INSERT INTO #dir EXEC master.dbo.xp_cmdshell @CMD

DELETE FROM #dir WHERE line IS NULL

SELECT * FROM #dir

DROP TABLE #dir

-- =============================================
Guillaume.

"Arnaud CAVELIER" a écrit :

Bonjour,

Il y a quelques temps Fred Brouard m'a proposé une procédure pour récupérer
le nom des fichiers d'un répertoire donné.

Cela a bien fonctionné jusqu'au jour où j'ai changé d'OS (ce matin en
l'occurence).

A priori, la structure de la LINE diffère d'un Windows XP Français à un
Windows 2003 Server Américain.

Est-il possible d'avoir une info plus précise sur le contenu de cette LINE ?
Ou comment être certain de la position du nom de fichier dans la chaine ?

Merci
Arnaud

"Fred BROUARD" wrote:

> Un petit exemple :
>
> DECLARE @OS_COMMANDE NVARCHAR(4000)
> SET @OS_COMMANDE = '''DIR C:*.txt'''
>
> CREATE TABLE #dir (line NVARCHAR(256))
>
> INSERT INTO #dir
> EXEC ('master..xp_cmdshell ' + @OS_COMMANDE)
>
> DELETE FROM #dir
> WHERE line IS NULL
>
> DELETE FROM #dir
> WHERE SUBSTRING(line, 1, 1) = ' '
>
> SELECT *
> FROM #dir
>
> A +



Avatar
Arnaud CAVELIER
Bonjour et merci c'est exactement ce qui me manquait !

Bravo et encore merci
Arnaud

"GNocent" wrote:

Salut,

Une solution pour le rencensement de fichiers d'un répertoire est de
modifier ton dir pour lui faire renvoyer des lignes plus simples à parser
(mais tu perds les infos sur la date et la taille) :

-- ============================================= >
DECLARE @CMD NVARCHAR(200)

SELECT @CMD = 'DIR /B /A-D C:*.txt'

CREATE TABLE #dir (line NVARCHAR(500))

INSERT INTO #dir EXEC master.dbo.xp_cmdshell @CMD

DELETE FROM #dir WHERE line IS NULL

SELECT * FROM #dir

DROP TABLE #dir

-- ============================================= >
Guillaume.

"Arnaud CAVELIER" a écrit :

> Bonjour,
>
> Il y a quelques temps Fred Brouard m'a proposé une procédure pour récupérer
> le nom des fichiers d'un répertoire donné.
>
> Cela a bien fonctionné jusqu'au jour où j'ai changé d'OS (ce matin en
> l'occurence).
>
> A priori, la structure de la LINE diffère d'un Windows XP Français à un
> Windows 2003 Server Américain.
>
> Est-il possible d'avoir une info plus précise sur le contenu de cette LINE ?
> Ou comment être certain de la position du nom de fichier dans la chaine ?
>
> Merci
> Arnaud
>
> "Fred BROUARD" wrote:
>
> > Un petit exemple :
> >
> > DECLARE @OS_COMMANDE NVARCHAR(4000)
> > SET @OS_COMMANDE = '''DIR C:*.txt'''
> >
> > CREATE TABLE #dir (line NVARCHAR(256))
> >
> > INSERT INTO #dir
> > EXEC ('master..xp_cmdshell ' + @OS_COMMANDE)
> >
> > DELETE FROM #dir
> > WHERE line IS NULL
> >
> > DELETE FROM #dir
> > WHERE SUBSTRING(line, 1, 1) = ' '
> >
> > SELECT *
> > FROM #dir
> >
> > A +
>


Avatar
Philippe T [MS]
Bonjour,

J'aime bien aussi cela :
http://usenet.jyxo.cz/cz.comp.microsoft.sql/0204/i-need-to-get-list-of-files-through-stored-procedure.html

----------------------------------------------------------------------
Philippe TROTIN - Microsoft Service France

"Arnaud CAVELIER" wrote in
message news:
Bonjour et merci c'est exactement ce qui me manquait !

Bravo et encore merci
Arnaud

"GNocent" wrote:

Salut,

Une solution pour le rencensement de fichiers d'un répertoire est de
modifier ton dir pour lui faire renvoyer des lignes plus simples à parser
(mais tu perds les infos sur la date et la taille) :

-- ============================================= >>
DECLARE @CMD NVARCHAR(200)

SELECT @CMD = 'DIR /B /A-D C:*.txt'

CREATE TABLE #dir (line NVARCHAR(500))

INSERT INTO #dir EXEC master.dbo.xp_cmdshell @CMD

DELETE FROM #dir WHERE line IS NULL

SELECT * FROM #dir

DROP TABLE #dir

-- ============================================= >>
Guillaume.

"Arnaud CAVELIER" a écrit :

> Bonjour,
>
> Il y a quelques temps Fred Brouard m'a proposé une procédure pour
> récupérer
> le nom des fichiers d'un répertoire donné.
>
> Cela a bien fonctionné jusqu'au jour où j'ai changé d'OS (ce matin en
> l'occurence).
>
> A priori, la structure de la LINE diffère d'un Windows XP Français à un
> Windows 2003 Server Américain.
>
> Est-il possible d'avoir une info plus précise sur le contenu de cette
> LINE ?
> Ou comment être certain de la position du nom de fichier dans la chaine
> ?
>
> Merci
> Arnaud
>
> "Fred BROUARD" wrote:
>
> > Un petit exemple :
> >
> > DECLARE @OS_COMMANDE NVARCHAR(4000)
> > SET @OS_COMMANDE = '''DIR C:*.txt'''
> >
> > CREATE TABLE #dir (line NVARCHAR(256))
> >
> > INSERT INTO #dir
> > EXEC ('master..xp_cmdshell ' + @OS_COMMANDE)
> >
> > DELETE FROM #dir
> > WHERE line IS NULL
> >
> > DELETE FROM #dir
> > WHERE SUBSTRING(line, 1, 1) = ' '
> >
> > SELECT *
> > FROM #dir
> >
> > A +
>




Avatar
Fred BROUARD
Arnaud CAVELIER a écrit:
Bonjour,

Il y a quelques temps Fred Brouard m'a proposé une procédure pour récupérer
le nom des fichiers d'un répertoire donné.

Cela a bien fonctionné jusqu'au jour où j'ai changé d'OS (ce matin en
l'occurence).

A priori, la structure de la LINE diffère d'un Windows XP Français à un
Windows 2003 Server Américain.



Exact, chaque proc doit être adpaté à l'OS...

Cependant on peut quand même déterminer certains paramètres !

Voici un petit exemple qui détermine dans une telle liste, l'ordre des
paramètres de date...

/******************************************************************************
-- création d'une fonction F_COUNTCHAR de comptage d'occurrence de caractères
******************************************************************************/
-- la fonction F_COUNTCHAR existe t-elle dans la base ? Si oui, la supprimer !

IF EXISTS (SELECT *
FROM INFORMATION_SCHEMA.ROUTINES
WHERE ROUTINE_CATALOG = DB_NAME()
AND ROUTINE_SCHEMA = USER
AND ROUTINE_NAME = 'F_COUNTCHAR'
AND ROUTINE_TYPE = 'FUNCTION')
DROP FUNCTION dbo.F_COUNTCHAR
GO

-- création de la fonction de comptage d'occurrence de caractères
CREATE FUNCTION F_COUNTCHAR (@STR NVARCHAR(4000), @CHAR CHAR(1))
RETURNS INTEGER
AS
BEGIN

-- effets de bord
IF @STR IS NULL RETURN NULL
IF @STR = '' RETURN 0

DECLARE @OUT INTEGER, @OFFSET INTEGER
SET @OUT = 0
SET @OFFSET = 0

WHILE CHARINDEX(@CHAR, @STR, @OFFSET) > 0
BEGIN
SET @OUT = @OUT +1
SET @OFFSET = CHARINDEX(@CHAR, @STR, @OFFSET) + 1
END

RETURN @OUT

END
GO


/******************************************************************************
-- détection du format horaire des fichiers de l'OS
******************************************************************************/

-- création d'une table temporaire de travail pour ce faire

-- la table temporaire locale #LINE_DATE existe t-elle dans la base tempdb
-- pour la session actuelle ? Si oui, la virer !
IF EXISTS (SELECT *
FROM tempdb.INFORMATION_SCHEMA.TABLES
WHERE TABLE_CATALOG = 'tempdb'
AND TABLE_SCHEMA = USER
AND TABLE_NAME = (SELECT name
FROM tempdb..sysobjects
WHERE id = OBJECT_ID('tempdb..#LINE_DATE')))
DROP TABLE #LINE_DATE
GO

-- créer la table temporaire locale #LINE_DATE
CREATE TABLE #LINE_DATE
(LINE VARCHAR(256),
D1 INT,
D2 INT,
D3 INT)

-- insertion des fichiers de la racine du lecteur C
INSERT INTO #LINE_DATE (LINE)
EXEC master..xp_cmdshell 'DIR "C:"*.* /A /-C /N'

-- troncature des lignes pour n'obtenir que la date
UPDATE #LINE_DATE
SET LINE = SUBSTRING(LINE, 1, 10)
WHERE LEN(LINE) > 10

-- suppression des lignes qui ne contiennent pas de slash ou sont vides
DELETE FROM #LINE_DATE
WHERE CHARINDEX('/', LINE) = 0
OR LINE IS NULL

-- suppression des lignes qui ne contiennent pas au moins deux slash
DELETE FROM #LINE_DATE
WHERE dbo.F_COUNTCHAR(LINE, '/') <> 2

-- le format de date est-il homogene ?
IF NOT EXISTS (SELECT COUNT(*)
FROM (SELECT DISTINCT CHARINDEX('/', LINE) AS BREAK_ONE,
CHARINDEX('/', LINE, CHARINDEX('/',
LINE)+1) AS BREAK_TWO
FROM #LINE_DATE) T
HAVING COUNT(*) = 1)
BEGIN
RAISERROR('Format de date non détectable', 16, 1)
RETURN
END
ELSE
-- récupération du format de date
SELECT CASE
WHEN D1 > 31 THEN 'Y'
WHEN D1 > 12 THEN 'D'
ELSE 'M'
END +
CASE
WHEN D2 > 31 THEN 'Y'
WHEN D2 > 12 THEN 'D'
ELSE 'M'
END +
CASE
WHEN D3 > 31 THEN 'Y'
WHEN D3 > 12 THEN 'D'
ELSE 'M'
END
FROM (SELECT DISTINCT (SELECT MAX(SUBSTRING(LINE, 1, CHARINDEX('/', LINE)-1))
FROM #LINE_DATE) AS D1,
(SELECT MAX(SUBSTRING(LINE, CHARINDEX('/', LINE)+1,
CHARINDEX('/', LINE, CHARINDEX('/', LINE)+1) -CHARINDEX('/', LINE)-1))
FROM #LINE_DATE) AS D2,
(SELECT MAX(SUBSTRING(LINE, CHARINDEX('/', LINE, CHARINDEX('/',
LINE)+1)+1, LEN(LINE) - CHARINDEX('/', LINE, CHARINDEX('/', LINE)-1)))
FROM #LINE_DATE) AS D3
FROM #LINE_DATE ) T

GO








Est-il possible d'avoir une info plus précise sur le contenu de cette LINE ?
Ou comment être certain de la position du nom de fichier dans la chaine ?

Merci
Arnaud

"Fred BROUARD" wrote:


Un petit exemple :

DECLARE @OS_COMMANDE NVARCHAR(4000)
SET @OS_COMMANDE = '''DIR C:*.txt'''

CREATE TABLE #dir (line NVARCHAR(256))

INSERT INTO #dir
EXEC ('master..xp_cmdshell ' + @OS_COMMANDE)

DELETE FROM #dir
WHERE line IS NULL

DELETE FROM #dir
WHERE SUBSTRING(line, 1, 1) = ' '

SELECT *
FROM #dir

A +







--
Frédéric BROUARD, MVP SQL Server, expert bases de données et langage SQL
Le site sur le langage SQL et les SGBDR : http://sqlpro.developpez.com
Audit, conseil, expertise, formation, modélisation, tuning, optimisation
********************* http://www.datasapiens.com ***********************