Remova o caminho da saída do comando find

29

Eu tenho um script bash para implantar código de um ambiente beta para um ambiente de produção, mas atualmente tenho que adicionar a lista de arquivos a um arquivo txt manualmente e, em algum momento, sinto falta de alguns. Basicamente, meu script de implantação cat / loops copia os arquivos. (db de exportações / importações também, mas isso não é relevante .. lol)

De qualquer forma, eu gostaria de usar o findcomando para gerar uma lista de arquivos modificados nos últimos 14 dias. O problema é que preciso remover o caminho ./para que o script de implantação funcione.

Aqui está um exemplo do uso do comando find:

encontrar . -type f -mtime -14> deploy.txt

Aqui está a linha que os gatos deploy.txtno meu script de implantação:

for i in `cat deploy.txt`; do cp -i /home/user/beta/public_html/$i /home/user/public_html/$i; done

Alguma idéia de como fazer isso usando o script bash?

Obrigado!

Mikey1980
fonte
3
Existe uma razão para você não usar apenas o rsync para isso? Parece que você pode estar tentando reinventar a roda e transformá-la em um triângulo.
precisa saber é o seguinte
necessidades ponto válido no entanto antes da implantação do deploy.txt é revisto e qualquer coisa que repara é removido
Mikey1980
1
Talvez execute o rsync no --dry-runmodo e envie isso para um arquivo para revisão?
precisa saber é o seguinte

Respostas:

36

Você pode usar a -printfopção de linha de comando com %fpara imprimir apenas o nome do arquivo sem nenhuma informação de diretório

find . -type f -mtime -14 -printf '%f\n' > deploy.txt

ou você pode usar o sed para remover o ./

find . -type f -mtime -14 | sed 's|^./||' >deploy.txt
Iain
fonte
Eu acredito que você tem que escapar do /..
EEAA
5
Não quando você usa |como delimitador.
user9517 suporta GoFundMonica
3
O uso %fremoverá todos os diretórios, não apenas ./. Isso interromperá o script de implantação se algum dos arquivos retornados por findestiver localizado em subdiretórios.
James Sneeringer
2
@Iain Você precisa escapar do pensamento .. E talvez seja melhor usar uma âncora de início de linha:s|^\./||
James O'Gorman
12
Use em %Pvez de %f. Isso apenas cortou o caminho indicado na linha de comando.
TrueY
11

O ./deve ser inofensivo. A maioria dos programas tratará /foo/bare /foo/./barcomo equivalente. Sei que não parece muito bom, mas com base no que você postou, não vejo razão para que o script falhe.

Se você realmente quer tirá-lo, sedé provavelmente a maneira mais limpa:

find . -type d -mtime 14 | sed -e 's,^\./,,' > deploy.txt

Se você estiver em um sistema com o GNU find (por exemplo, a maioria dos sistemas Linux), poderá fazê-lo de uma só vez com find -printf:

find . -type d -mtime 14 -printf "%P\n" > deploy.txt

Os %Pretornos o caminho completo de cada arquivo encontrado, menos o caminho especificado na linha de comando, até e incluindo a primeira barra. Isso preservará todos os subdiretórios em sua estrutura de diretórios.

James Sneeringer
fonte
1
O ./prefixo é realmente um recurso; sem ele, a saída da tubulação para outros comandos não funcionará corretamente, por exemplo, para nomes de arquivos que começam com um traço.
tripleee
1
@ tripleee - Eu entendo a utilidade dele, mas o OP perguntou especificamente como retirá-lo porque estava causando problemas em seu script de implantação. Claro, pode haver maneiras melhores de fazer o que ele precisa, mas isso é uma toca de coelho muito além do que foi solicitado.
precisa
7

Por que você precisa retirar o ./? É válido ter um caminho. tão

cp -i dir1/./somefile dir2/./somefile

está tudo bem!

Mas se você deseja remover o nome do diretório em find, você pode usar o %Parg para -printf.

homem encontrar (1) diz:

         %P     File's name with the name of the  command  line  argument
                 under which it was found removed.

Um exemplo

$ find other -maxdepth 1
other
other/CVS
other/bin
other/lib
other/doc
other/gdbinit
$ find other -maxdepth 1 -printf "%P\n"

CVS
bin
lib
doc
gdbinit

Mente a primeira linha vazia! Se você quiser evitá-lo, use-mindepth 1

$ find other -mindepth 1 -maxdepth 1 -printf "%P\n"
CVS
bin
lib
doc
gdbinit
TrueY
fonte
3

Bem, você tem algumas opções. Você pode usar a -printfopção find para imprimir apenas o nome do arquivo, ou pode usar uma ferramenta como sed para simplesmente remover o arquivo ./.

# simply print out the filename, will break if you have sub-directories.
find . -mtime -14 -printf '%f\n'

# strip a leading ./
find .  -mtime -14 | sed -e 's/^\.\///'
Zoredache
fonte
Você pode me dar um exemplo de seu uso? Desculpe, o linux não é realmente o meu forte.
Mikey1980 27/01
2
Olhe novamente, há exemplos.
precisa saber é o seguinte
Concordo - tente, você não vai machucar nada executando uma combinação de find e sed.
EEAA
3

A solução "find -printf" não funcionará no FreeBSD porque o find não possui essa opção. Nesse caso, o AWK pode ajudar. Ele retorna um sobrenome ($ NF), para que possa funcionar em qualquer profundidade.

find /usr/local/etc/rc.d -type f | awk -F/ '{print $NF}'

PS: extraído do livro "Programação de shell Linux e Unix" de D.Tansley

user221341
fonte
2

Uma solução rápida, se eu entendi corretamente a pergunta, está usando cuta saída do findcomando:

$> find . -type f -mtime -14 | cut -b 3- > deploy.txt

Isso removerá os primeiros caracteres de cada linha do resultado (no seu caso ./). Provavelmente não é a melhor solução, mas funciona no seu cenário.

Alessandro Dotti Contra
fonte
1

sed é perfeito para esse tipo de coisa.

$ find . -type f -mtime -14 find . | sed 's/^\.\///' > deploy.txt
EEAA
fonte
1

Não sei de que tipo de nome de arquivo estamos falando, mas qualquer coisa com espaços ou novas linhas coloca a maioria das soluções aqui em risco.

Minha sugestão seria usar a expansão de parâmetros do shell para remover os caracteres de cada nome de arquivo:

find . -mtime -14 -exec sh -c 'printf "${0#./}\n"' {} \; >deploy.txt

Se você realmente gosta de pipes, pode usar um delimitador "seguro", como um nulo, com xargs para receber cada nome de arquivo:

find . -mtime -14 -print0 | xargs -0 -n 1 sh -c 'printf "${0#./}\n"' >deploy.txt

Lembre-se de que a saída disso NÃO é delimitada por nulo; portanto, embora possa ser suficiente para uma verificação ocular, nenhuma dessas soluções produz um arquivo deploy.txt que é seguro para uso em automação, a menos que você tenha muita confiança em sua fonte nomes de arquivos.

ghoti
fonte