Usar comando shell para manipular arquivos [quase resolvido]

Iniciado por coelhuturbo, 05 de Junho de 2009, 09:34

tópico anterior - próximo tópico

coelhuturbo

Meu primeiro post sobre Linux!
Desde já obrigado a quem quer que tenha sido enviado para me ajudar.

Tenho diretório 1 e diretório 2.
A pasta 1 tem subdiretórios e estes também tem subdiretórios. Este está bem organizados.
Diretório 2 não tem subdiretórios. Fiz uma pesquisa em 1 com *.extensão para encontro todos
os arquivos que queria ignorando os subdiretórios. Os movi para 2 para serem editados.
Agora tenho 2 com os arquivos como quero mas quero eles devolta a 1 em seus lugares.
Minha missão:
Mover arquivos da pasta "2" para os subdiretórios onde eles tem arquivos duplicados na pasta "1".

Existe alguma variável em shell ou algo que consiga este objetivo?
Não encontrei nada semelhante pesquisando.

Xterminator

Eita que complicado, tipo assim você sabe o local de origem dos arquivos?
porque um simples cp ou mv usando  a opção -f mais alguns curingas iria copiar e já substituir o arquivo de mesmo nome.
como você mesmo disse se os diretórios e subdiretórios estão bem organizados "você com certeza, sabe o local para onde os arquivos deverão ser copiados ;-)"

coelhuturbo

#2
Seria muito trabalhoso fazê-lo na unha, o diretório A contém diversos subdiretórios e uma parte destes, outros subdiretórios.
Isso ainda com B com várias centenas de arquivos.

Estou lendo:
http://blog.cidandrade.pro.br/tecnologia/linux-unix-comando-cp/, mas mieu problemas é de como usar os comandos em conjunto.
eu não sei bem de script, ou o que for necessário para istá ação.

Resumindo:
Arquivos de diretório B sobrepondo seus arquivos duplicados em diretório A sem alterar a estrutura de A com tudo ficando no mesmo lugar.

clcampos

Movido para Programação e Scripts.

Olha fazer um script para fazer o que deseja é bem possível, mas para algo assim tão particular você teria que dar todos os detalhes possíveis, como quais as extensões envolvidas, para que (sub)diretório cada extensão seria movido.

Talvez seja mesmo mais fácil você fazer isto ai... exemplos de shell script para te ajudar é que não faltam aqui no fórum.

Observação, talvez se você ordenar o diretório 02 por extensão no nautilus fique mais fácil você mover os arquivos na mão.
Cristiano/Timóteo - MG
.: Como Fazer Perguntas de Forma Inteligente :.                
Com dúvida? pesquise!

coelhuturbo

#4
Eu já fiz a parte de separar os arquivos que quero!

Eles foram todos para o segundo diretório. Usei sim *.mp3 para isto.
Vamos lá..
O problema é que o primeiro diretório está organizado em subdiretórios.

A
|___B
|___C___C1
|___D     |_C1a
|___E     |_C1b
|___F_F1
          |_F1a
          |_F1b

Alguém consegue ter uma idéia para entender? Mas eu quero que os arquivos que copiei e editei no segundo diretório voltem para onde estavam antes. Levando em conta que, talvez, possam ir sendo guiados pelos seus nomes duplicados. Apaguem os anteriores e vivendo felizes para sempre.

coelhuturbo

Diretório A tem subdiretório organizando seus arquivos.
Pega o que quero de A, manda para B.
B não tem subdiretórios o organizando.
Tudo em B é editado e passa a ficar pronto.
Os arquivos agora tem que voltar para A no lugar onde estavam antes.
Os arquivos antigos que foram copiados e editados não precisam mais existir.
Seria bom que os que ficaram e não foram editados nem movidos sobrevivecem em A.
Mas o mais importante agora é que a organização de subdiretórios de A se mantenha.

ANY HELP?

raidicar

Deixa eu ver se entendi essa salada.
Diretório "A" contém arquivos e uma arvore de subdiretórios recheado de diretórios e arquivos.
Vc deseja copiar todos os arquivos com uma determinada extensão (ex: *.mp3) para a raiz do diretório "B", sem recriar a estrutura de diretórios existente em "A".
Após editar os arquivos você deseja retorna-los ao local antigo, preservando a estrutura de diretórios existente em "A", substituindo assim os arquivos mais antigos pelos arquivos editados.

Não é dificil de fazer isso, seria muito mais fácil porém, se a estrutura fosse recriada no diretório "B", um script com o rsync resolveria pois, após editar, bastaria sincronizar "A" com "B" para que os arquivos alterados em "B" sobreporem os arquivos antigos em "A", mas não tem problema. Eu não gosto muito, mas posso bolar um script, até mais longo que o normal, com muitas condições para que entendesse o funcionamento passo a passo do script com mais facilidade, cabendo a você, a tarefa de simplifica-lo, mas preciso saber se realmente entendi o que deseja realizar, além de, claro, saber o caminho da pasta "A" e "B".
Quem ama extremamente, deixa de viver em si e vive no que ama. Na vida três coisas são certas, o amor, a morte e o Linux !
Se Platão disse, então realmente sofremos de uma perigosa doença mental.

coelhuturbo

Companheiro raidicar, eu coloco os diretórios onde tu quiser!
O meu problema começa como citou mas o de tirar de "A" apenas os que eu quero é fácil. Já o realizei e já editei os arquivos.
O meu problema é que tenho que fazer tudo isso para poder editar em massa e não dá para fazer isso diretório por diretório. Fica muito mais rápido e simples se todos os arquivos estiverem juntos e em um único diretório. Para isso exite "B".

O diretório "A" está lá tranquilo. "B" está lá com os arquivos sem a estrutura de "A" mas já com todos os arquivos editados sem terem seus nomes ou extensões alteradas.
É exatamente o que entendeu só que sem a parte que eu fiz mais facilmente. Continuo pesquisando, mas as explicações para comandos como cp e mv são muito resumidas e não parece ter ninguém com este problema neste fórum. Estou revirando a internet mas devo estar olhando de modo erróneo.

Gostaria ao menos de saber qual conhecimento preciso ter mais especificamente para realizar esta tarefa. Vou tentar entender mais sobre script..
Pode, por exemplo, existir um script semelhante para alterá-lo para está função?

raidicar

#8
Citação de: coelhuturbo online 06 de Junho de 2009, 02:20
Companheiro raidicar, eu coloco os diretórios onde tu quiser!
Ok! Isso não ficou muito legal..., mas deixemos de lado essa colocação e sigamos em frente.  ;D

Coelhuturbo, eu não tenho um script semelhante para que com algumas alterações você possa utiliza-lo e, sinceramente, não seio onde tem pois nunca vi ninguém com o mesmo problema, mas como eu disse, a solução não é difícil.
o comando cp que você está estudando nem entra nesse caso, passa longe da solução que precisa e por estar totalmente longe da solução, vou postar além do comando que precisa, uma "biblia", para que todos que tiverem o mesmo problema entendam exatamente como a coisa funciona. Se quiser apenas a resposta, vá até o final, se quiser entende-lá, leia tudo com atenção, OK?

O conhecimento que você precisa ter é:
1 - Comando Find.
2 - Váriaveis (Não chega a ser necessário, mas é bom saber)
3 - Comando Rsync.

"Problema" do rsync:
1 - Não é bidirecional, pelo menos já li o man do rsync quase completo e não encontrei um parâmetro que o torna bidirecional (alguém me corrija se estiver errado).
Isso significa que ele sincroniza o diretório A com o diretório B, ou seja, se um arquivo for alterado em B, ao sincronizar A com B o mesmo não será atualizado no diretório A, para isso é preciso um segundo comando sincronizando o diretório B com o diretório A.
Quando além da origem, o destino também sofre alterações, essa é a única forma de deixar o conteúdo de duas pastas sempre idênticas

Tendo dito essa informação que é importante saber, voltamos ao assunto.

Primeiro, veja o comando rsync que poderia fazer esse trabalho:
rsync -Cravzpu --existing /home/coelhuturbo/editados /home/coelhuturbo/originais

Nesse caso, os arquivos modificados por você na pasta editados serão copiado para a pasta originais, mas isso somente se na pasta originais existirem arquivos com o mesmo nome e extensão dos arquivos na pasta editados. Caso existam, os arquivos mais antigos que estão na pasta originais serão substituidos pelos arquivos mais novos que estão na pasta editados, caso não existissem, nada seria efetuado, isso graças a opção --existing e a opção -u do parâmetro -Cravzpu inserida no comando rsync.
Com relação aos outros parametros (-Cravzp), pesquise no manual do rsync (é só digitar man rsync no terminal).
Ex: se inserir o q (Cravzpuq), de quiet, a cópia será silenciosa, ou seja, nada será exibido no terminal.

Isso, em teoria, solucionaria o seu problema, mas como eu disse, não sei a quantidade de subdiretórios e nem a freqüência com que os mesmos são criados.
Suponto que sejam 20 diretórios e subdiretórios no total, e que raramente um novo diretório é criado, bastaria um script com 20 linhas de comandos como o que está acima para fazer o que deseja.Ex:
#!/bin/bash
rsync -Cravzpu --existing /home/coelhuturbo/editados /home/coelhuturbo/originais
rsync -Cravzpu --existing /home/coelhuturbo/editados /home/coelhuturbo/originais/subori01
rsync -Cravzpu --existing /home/coelhuturbo/editados /home/coelhuturbo/originais/subori01/subori001
rsync -Cravzpu --existing /home/coelhuturbo/editados /home/coelhuturbo/originais/subori02/
rsync -Cravzpu --existing /home/coelhuturbo/editados /home/coelhuturbo/originais/subori03/
etc...

Um loop poderia ser realizado facilmente se as suas pastas fossem nomeadas com caracteres e em ordem numéricas... Claro que não é o caso.

Mas isso é meio trabalhoso, supondo que você tenha muitos diretórios e subdiretórios, algo em torno de 200 pastas no total e que praticamente todo dia fosse adicionado mais diretórios e subdiretórios, nesse caso, a solução acima seria inviável, pois exigiria uma administração complexa demais, nos forçado a automatizar essa tarefa.

Nesse ponto entra o comando find.
find /home/coelhuturbo/originais/ -name *.txt
Nesse caso, o comando find pesquisa todos os arquivos com extensão txt dentro do diretório e subdiretórios de originais.
Creio que foi o find que você utilizou para jogar todos os arquivos dos diretórios e subdiretórios de A para a raiz de B.

Outro comando find...
find /home/coelhuturbo/originais/ -maxdepth 10 -type d
Esse comando mostra a arvore de diretórios começando em originais com até 10 subdiretórios dentro dela.

Como já lhe informei sobre o rsync e o find, eu iria lhe propor o desafio de:
1 - Listas os diretórios e subdiretórios com o find.
2 - armazenar cada linha do resultado em uma variável, assim, cada variável seria o destino.
3 - sincronizar com o rsync a origem dos dados, que seria a pasta editados com cada uma das variáveis definidas anteriormente, ou seja, o destino, que seria cada diretório e subdiretório da pasta originais.
Mas hoje é segunda então não vou estragar seu inicio de semana. ;D

Antes de prosseguir, é importante saber de outro "problema" do rsync.
Eu li o man do rsync e não encontrei uma opção ao comando rsync que o faça sincronizar uma origem com vários destinos, (me corrijam se estiver errado), ou seja, o mesmo sincroniza o A para B, e pronto, se quiser sincronizar A para C, A para B/A e A para B/A/F, é necessário uma nova linha de comando para cada, resumindo, uma linha de comando para cada destino, isso tornaria o processo lento e doloroso, além de difícil de administrar, pois quanto maior o numero de subdiretórios na pasta originais, mais comandos teríamos de dar e é impossível fugir disso, foi por esse motivo que não lhe pedi para se virar com variáveis.

Nesse caso, burlamos tudo isso e chegamos onde você espera unindo os comandos rsync e find.
A idéia é:

1 - Localizar um arquivo por uma determinada extensão pelo comando find na pasta e subpastas de DESTINO.
(no caso, como exemplo, a pasta originais, pois ela é o destino dos arquivos alterados e que estão em outro local)

2 - Ao localizar um arquivo, parar, realizar o sincronismo, ou seja, ir buscar um arquivo com o mesmo nome na pasta de ORIGEM.
(no caso, como exemplo, a pasta editados é a origem, pois dela sairão os arquivos para a pasta originais)

2.1 - Ao localizar o arquivo, comparar a data de alteração para decidir se deve haver substituição.
(se o arquivo na pasta editados for mais novo que o arquivo na ou subpasta originais, substitua-o)

3 - Agora, após o comando find localizar um arquivo e o comando rsync substitui-lo por outro mais novo com o mesmo nome, o comando find deve continuar a procura pelo próximo arquivo. E esse processo se repete até que todos os diretórios e subdiretórios de ORIGINAIS sejam vasculhados pelo comando find.

Isso tudo realizado por uma única linha de comando em velocidade impressionante.
A linha de comando é:
find /home/coelhuturbo/originais/ -name *.txt -type f -exec rsync -Cravzpu /home/coelhuturbo/editados/*.txt {} \;
Altere *.txt pela extensão que utiliza.

Abaixo, apenas informações que acredito que você nem precise, mas apenas para deixar registrado, já digitei tanto mesmo...

Abra o editor de texto, digite o conteúdo abaixo e salvando com o nome de coelhoturbo.

#!/bin/bash
find /home/coelhuturbo/originais/ -name *.txt -type f -exec rsync -Cravzpu /home/coelhuturbo/editados/*.txt {} \;

agora de os comandos sudo chmod +x coelhuturbo e o comando cp coelhuturbo /usr/bin/

Agora você pode executar o sincronismo da seguinte forma:
1 - digitando coelhuturbo no terminal.
2 - pode criar um lançador no desktop e executar o sincronismo dando um duplo clique...


ok?

Abraços...

Quem ama extremamente, deixa de viver em si e vive no que ama. Na vida três coisas são certas, o amor, a morte e o Linux !
Se Platão disse, então realmente sofremos de uma perigosa doença mental.

coelhuturbo

Parece excelente.. eu ainda não testei por estar em outro PC, mas parece que vai resolver meu problema pelos próximos vinte anos!
Eu vou testar assim que possível e colocar a resposta.

Enquanto esperava alguma luz aqui continuei lendo em outros locais e nada encontrado. Um amigo me falou sobre o python, mas o meu interesse seria na mobilidade, poder fazer isto sem precisar de nada além do PC com o shell por ter que usá-lo em vários PC meio que fraquinhos que são de usuários simples para trabalhos de escritórios.

Assim como na frase satírica, continuo ansioso por ter este problema resolvido.

Muito Obrigado!

marcospinho

#10
o comando não funcionou como eu esperava será que eu fiz algo errado?
o caminho para as pastas que eu quero sincronizar é /media/MARCOS/(pendrive)
e /media/dados/ (partição de dados do computador)
o arquivo que se refere abaixo parece ser esse /media/dados/jogos/AncientSecrets_10128.exe

marcos@ubuntu:~$ find /media/MARCOS/ -name *.* -type f -exec rsync -Cravzpu /media/dados/*.* {} \;
find: caminhos devem preceder a expressão: Ancient Secrets.lnk
Uso: find [-H] [-L] [-P] [-Onível] [-D help|tree|search|stat|rates|opt|exec] [caminho...] [expressão]

ah! e onde coloca o -v para eu ver o comando sendo executado?
celeron 2.66Ghz, 1G Ram, DVDrw monitor AOC 17pol, HDsata500g, L-Ubuntu Maverick-i386, /root 20G /home 50G /win 40G /win7 50G /dados 20G /teste(nathy+Kde) 15G /acervo 220G  Linux Counter #478143. Ubuntu counter is # 24448

raidicar

#11
Opa, para tudo! companheiro marcospinho, você leu atentamente o problema postado?
O usuário coelhuturbo relata o seguinte problema:
1 - jogar todos os arquivos de um diretorio e todos os arquivos de seus subdiretório dentro de uma unica pasta de destino.
Ex: jogar todas as musicas do computado na raiz de uma pasta chamada Songs.
2 - Feito isso, a pasta songs tem arquivos e somente arquivos, nenhum subdiretório e esses arquivos são editados e alterados.
3 - Por fim, esses arquivos alterados tem de voltar para a Origem, substituindo os arquivos antigos.
Esse é um problema peculiar, sinceramente não esperava ver outra pessoa com esse problema e a solução que eu postei é pra fazer exatamente isso, que é Localizar os dados antigos e comparar com os dados Editados ( isso se os mesmos existirem) que estão dentro da raiz de uma pasta afim de substituir os arquivos na pasta de origem por caso os mesmos estejam desatualizados.
É isso o que você quer fazer?
Ou você quer somente sincronizar a pasta /media/MARCOS/(pendrive) com e /media/dados/? E se os dados que em /media/dados/ estiverem desatualizados serão
substituidos pelos dados que estão em /media/MARCOS/(pendrive) ? Ou seja, deseja realizar um simples backup incremental. É isso?
Quem ama extremamente, deixa de viver em si e vive no que ama. Na vida três coisas são certas, o amor, a morte e o Linux !
Se Platão disse, então realmente sofremos de uma perigosa doença mental.

marcospinho

o que acontece é o seguinte: eu edito alguns arquivos no computador e quero levar para o trabalho, por isso quero Sincronizar com o pendrive, depois eu edito uns arquivos no trabalho e quero sincronizar com o computador de casa
que graças a um script fornecido por voce no outro tópico os dois dispositivos pendrive de parição de dados estão com a mesma estrutura.
tem mais se por acaso eu quizer que alem de Sincronizar, eu quizer que os arquivos novos do pendrive sejam copiados para o computador inclusive criando as respectivas pastas novas?

OUTRA: eu pensei em duas coisas, o sincronismo poderia ser acionado na montagem do pendrive e conter as linhas de comando para sincronismo nos dois sentidos-perigo-? eu gostaria que isso ficasse oculto no pendrive assim: .sincronismo.sh e pudesse atribuir, no windows, como arquivo oculto também. Ou Criar dois atalhos na minha Dock para fazer o serviço sob demanda.
celeron 2.66Ghz, 1G Ram, DVDrw monitor AOC 17pol, HDsata500g, L-Ubuntu Maverick-i386, /root 20G /home 50G /win 40G /win7 50G /dados 20G /teste(nathy+Kde) 15G /acervo 220G  Linux Counter #478143. Ubuntu counter is # 24448

raidicar

#13
Citarah! e onde coloca o -v para eu ver o comando sendo executado?
O loco, o parametro já está lá: rsync -Cravzpu.

CitarOUTRA: eu pensei em duas coisas, o sincronismo poderia ser acionado na montagem do pendrive e conter as linhas de comando para sincronismo nos dois sentidos-perigo-? eu gostaria que isso ficasse oculto no pendrive assim: .sincronismo.sh e pudesse atribuir, no windows, como arquivo oculto também. Ou Criar dois atalhos na minha Dock para fazer o serviço sob demanda.
http://ubuntuforum-br.org/index.php/topic,50975.0.html
Aqui eu postei um script que faz isso e, além disso, o script fica no micro e não no pendrive, então, não precisa se preocupar em esconder o arquivo o pendrive.
Com relação a sincronismo nos dois sentidos, a resposta já postei aqui:
http://ubuntuforum-pt.org/index.php/topic,46562.msg275872.html#msg275872
Essa resposta na verdade se encaixa melhor ao seu problema.

Citartem mais se por acaso eu quizer que alem de Sincronizar, eu quizer que os arquivos novos do pendrive sejam copiados para o computador inclusive criando as respectivas pastas novas?
É exatamente isso que o rsync faz, sincronismo de pastas e arquivos, ou seja, se criar uma pasta na origem, ao sincronizar, ela será criada no destino. No link acima, onde é feito o sincronismo nos dois sentidos, não importa onde a pasta nova foi criada, se no computador ou no pendrive, ao término do sincronismo, a pasta existirá nos dois lugares. Faça alguns tetes com o rsync para compreende-lo. Crie umas pastas e subpastas, crie alguns arquivos de texto e teste o rsync, imaginando varias situações.

Abraço.
Quem ama extremamente, deixa de viver em si e vive no que ama. Na vida três coisas são certas, o amor, a morte e o Linux !
Se Platão disse, então realmente sofremos de uma perigosa doença mental.