quinta-feira, 14 de março de 2013

SQL Server - entendendo o master.dbo.xp_dirtree para listar conteúdo de um diretório

No SQL Server, para listar os arquivos e pastas de um diretório, utilizamos o comando master.dbo.xp_dirtree

Esta procedure possui 3 parâmetros:

  1. Directory - este parâmetro indica o diretório cujo conteúdo você deseja listar
  2. Depth - este parâmetro indica quantos níveis de subpasta você deseja listar. 0 irá listar todas as subpastas.
    • 0 - lista todas as subpastas
    • 1 - lista somente a pasta indicada no parâmetro directory
    • 2- lista a pasta indicada no parâmetro directory + uma subpasta
    • ... e assim por diante
  3. File - indica o que você deseja listas no seu diretório:
    • 0 - somente pastas
    • 1 - pastas e arquivos
Esta procedure retorna 3 colunas
  • Name - nome do arquivo ou pasta
  • Depth - indica o nível em que o arquivo/pasta está (1 - está na pasta, 2 - está na subpasta, etc)
  • IsFile - 0 indica que é uma pasta e 1 indica que é um arquivo.

==================================================
Exemplo:
===================================================

Tenho a seguinte estrutura:
  • C:\Pasta1
    • Arquivo1.txt
    • Arquivo11.txt
    • Pasta2
      • Arquivo2.txt
      • Arquivo22.txt
      • Pasta3
        • Arquivo3.txt
        • Arquivo33.txt

O comando abaio irá listar todos os arquivos e pastas, mas somente no primeiro nível, ou seja, somente o conteúdo do diretório C:\Pasta. Não irá listar o conteúdo das sub-pastas.
--------------------------
CREATE TABLE #FileList(Name varchar(200), depth numeric, IsFile numeric) 
INSERT INTO #FileList exec master.dbo.xp_dirtree 'C:\Pasta1', 1, 1 

select * from #filelist
drop table #filelist
---------------------------

O comando abaixo irá listar o conteúdo da Pasta1 e o conteúdo da pasta2 (segundo nível)
exec master.dbo.xp_dirtree 'C:\Pasta1', 2, 1 


O comando abaixo irá listar o conteúdo da Pasta1 , pasta2 (segundo nível) e pasta 3 (terceiro nível)
exec master.dbo.xp_dirtree 'C:\Pasta1', 3, 1 


Caso você execute desta forma, a procedure irá retornar apenas as coluna Name e Depth, pois, uma vez que você não está listando arquivos, você não precisa da coluna IsFile.

exe master.dbo.xp_dirtree 'C:\Pasta1', 1, 0   
ou
exe master.dbo.xp_dirtree 'C:\Pasta1', 1


10 comentários:

Unknown disse...
Este comentário foi removido pelo autor.
Unknown disse...

Olá,
to fazendo uma proc em sql server, que contem esse comando... (xp_DIRTREE), só que preciso ir alem, preciso pegar os arquivos .txt, que ele retorna, e fazer um bulk insert de todos.
Poderia me ajudar ??

Felipe Teixeira disse...

Oi, Simone tenho um código que faz isso, vou postar aqui nos comentários

Unknown disse...

Oi Felipe, fico aguardando ansiosamente ... =)

Felipe Teixeira disse...


DECLARE @SQL varchar(3000)
DECLARE @RETORNO int
DECLARE @sServidor varchar(200)
DECLARE @CaminhoCompletoLer varchar(200)
DECLARE @FileName varchar(300)

CREATE TABLE #ArquivosTXT ([NAME] varchar(300)
,DEPTH NUMERIC
,ISFILE NUMERIC)


--Carrega lista de arquivos que existem na pasta na na tabela temporária
INSERT INTO #ArquivosTXT exec master.dbo.xp_dirtree 'c:\Diretorio_ler\', 1, 1 --(Param1: Diretório / Param2: Nível da pasta / Param3: 1= exibir somente arquivos)

--apaga a tabela temporária, caso já exista
IF EXISTS ( SELECT * FROM [tempdb].[sys].[objects] WHERE name = '##dadosarquivo' )--AND type in (N'U'))
drop table ##dadosarquivo

--cria tabela temporaria exatamente com as mesmas colunas do arquivo TXT, na sequencia que estão no arquivo
create table ##dadosarquivo ( campo1 varchar(100)
,campo2 varchar(100)
,campo3 varchar(100) )

--Criar cursor para varrer a lista de arquivos da pasta
DECLARE C_ARQUIVOS CURSOR FOR
SELECT NAME FROM #ArquivosTXT
WHERE ISFILE = 1 --Somente arquivos
AND SUBSTRING(UPPER(NAME), LEN(NAME) - 2, 3) ='TXT'

OPEN C_ARQUIVOS
FETCH NEXT FROM C_ARQUIVOS INTO @FileName


WHILE @@FETCH_STATUS = 0
BEGIN
SET @CaminhoCompletoLer = 'c:\Diretorio_ler\' + @FileName

--INSERE OS DADOS DO ARQUIVO TEXTO NA TABELA TEMPORÁRIA
----------------------------------------------------------------------------------------------------------
SET @SQL = 'use dbtur3_9 bulk insert ##dadosarquivo ' + -- inserir na tabela desejada
' from ''' + @CaminhoCompletoLer + ''' '+ -- caminho do arquivo e nome do arquivo
'with ' +
'( fieldterminator = ''' + CHAR(9) + ''' ,' + -- caractere que separa os campos no arquivo (Neste exemplo: Char(9) = TAB)
' rowterminator = ''\n'' )' -- referencia para fim da linha

EXEC (@SQL)

SELECT * FROM ##dadosarquivo
FETCH NEXT FROM C_ARQUIVOS INTO @FileName
END

Unknown disse...

Felipe, vou testar e te falo.

Muito obrigada!

Unknown disse...

Felipe deu muito certo.

Muitíssimo obrigada novamente (:

Unknown disse...

Felipe, olha eu aqui de novo --"

Se eu quisesse importar os arquivos, um por um, e não todos de uma vez .. voce saberia me informar?

Felipe Teixeira disse...

Oi Simone,

você pode adicionar um TOP 1 no seu select
SELECT TOP 1 NAME FROM ##Arquivos...

Mas depois de processar o arquivo você teria que mover o arquivo ou excluí-lo, usando a procedure:

exec XP_CMDSHELL 'MOVE ' + @caminhoOrigem + ' ' + @caminhoDestino

(*caminho e nome do arquivo)

Desta forma, ele irá pegar sempre o primeiro arquivo. Como você moveu o anterior, o primeiro arquivo da próxima execução será próximo.

Fabio disse...

Boa tarde,

O que vc fez me ajudou bastante ... mas olhe o que eu preciso fazer, veja se consegue me ajudar.

Tenho pasta:
C:\TESTE
e a pasta C:\ABCD dentro da pasta ABCD possui várias outras pastas.

Preciso olhar na pasta C:\TESTE copiar somente os arquivos .XML que não estão na pasta C:\ABCD e nem nas suas subpastas.

Como eu poderia fazer isso?

Obrigado