/ bin / ls: Lista de argumentos muito longa

2

Eu sou uma pessoa de biologia e estou executando um programa chamado autodock. Eu tenho alguns arquivos da biblioteca ZINC no formato .mol2. Conforme o requisito, eu preciso dividir esses arquivos com o comando csplit e recebi todo o conteúdo do meu diretório. O arquivo principal foi dividido em muitos arquivos pequenos. Todo nome de arquivo é assim: ZINC14382748.mol2 . Agora eu tenho que mudar todos esses arquivos para o formato pdbqt e eu tenho que usar o seguinte script:

#!/bin/csh # # $Id: ex02.csh,v 1.5 2007/07/19 21:52:59 rhuey Exp $ 
# 
# use the 'prepare_ligands.py' python script to create pdbq files 
cd $VSTROOT/VirtualScreening/Ligands 
foreach f ('ls *') echo $f pythonsh ../../prepare_ligand4.py -l $f -d ../etc/ligand_dict.py end 

Quando eu uso, diz

/bin/ls: Argument list too long

Em suma, após a conclusão bem sucedida, duplicará o número de arquivos acima em outro formato. Então, existe alguma solução razoável para resolver este problema?

    
por Ash 09.07.2016 / 05:13

4 respostas

6

  1. Não analise a saída de ls . Apenas diga foreach f (*) . Além disso,
  2. Você deve sempre citar suas referências de variáveis de shell (por exemplo, "$f" ) a menos que você tenha um bom motivo para não e você tem certeza que sabe o que está fazendo.
por 09.07.2016 / 06:52
2

A origem do problema é que você tem muitos arquivos pequenos.

Se eu estiver lendo corretamente, você tem mais de 14 milhões arquivos. Não há como qualquer shell ter mais de 14 milhões de nomes de arquivos na linha de comando. Além de que. seus nomes de arquivos parecem ter cerca de 18 caracteres, de modo que são aproximadamente 18 * 14M ou cerca de 252 megabytes apenas para armazenar os nomes dos arquivos.

bash , por exemplo, tem um limite de 128 KB. sempre ligeiramente menor que 252MB. Não tenho ideia do limite csh porque não o uso. É improvável que seja maior que o limite de comprimento da linha de comando do bash. Certamente não será 252MB ou maior.

No entanto, nem tudo está perdido, você pode usar find ... -exec .

find . -maxdepth 1 -type f -name '*.mol2' \
  -exec pythonsh ../../prepare_ligand4.py -l {} -d ../etc/ligand_dict.py \;

Isso executará prepare_ligand4.py ONCE para cada arquivo, portanto, levará um longo tempo muito . Você pode ser capaz de acelerar um pouco (não muito, não com 14 + M arquivos para processar) usando find ... -print0 com xargs -0 -P ... ou GNU parallel -0 ... em vez de find ... -exec

Uma solução muito melhor seria baixar o código-fonte para prepare_ligand4.py e modificá-lo para que você possa fornecer um arquivo grande (por exemplo, o arquivo original antes de csplit -ing) e ele processará cada bloco individualmente. Será muito mais rápido e mais fácil de trabalhar. Você provavelmente ainda terá mais de 14 milhões de arquivos de saída (assumindo que um arquivo de saída combinado seria inútil ... se não estiver com sorte!), Mas isso é melhor do que ter arquivos de entrada de 14M e arquivos de saída de 14M. / p>

Isso, é claro, exigiria alguma habilidade com python de programação.

Talvez alguém já tenha encontrado o mesmo problema e tenha escrito sua própria versão aprimorada de prepare_ligand4.py . Vale a pena gastar algum tempo pesquisando, ou talvez tente o Autodock Forum ou até mesmo entrar em contato com o autor da Autodock.

    
por 09.07.2016 / 17:41
1

Você obviamente tem muitos arquivos. Considere usar o link do GNU Paralelo O 'ls -U' não classifica os arquivos e, em seguida, é mais rápido.

cd $VSTROOT/VirtualScreening/Ligands
ls -U ZINC* | parallel echo {} \; pythonsh ../../prepare_ligand4.py -l {} -d ../etc/ligand_dict.py

Eu não entendo porque você faz eco. Você analisa um novo roteiro? Meu palpite é que 'prepare_ligand4.py' é o script para conversão e então isso deve fazer o trabalho (em paralelo):

cd $VSTROOT/VirtualScreening/Ligands
ls -U ZINC* | parallel pythonsh ../../prepare_ligand4.py -l {} -d ../etc/ligand_dict.py
    
por 09.07.2016 / 13:16
1

Eu resolvi o problema, deixe-me compartilhar com você. Renomear o bash.csh para bash.sh, Em seguida, mudo o meu script para executá-lo no bash. Aqui está o meu novo script para ajudar no futuro para o mesmo problema.

#!/bin/bash
cd $VSTROOT/VirtualScreening/Ligands/
for f in ZINC*.mol2
do
    echo "$f"
    pythonsh ../../prepare_ligand4.py -l "$f" -d ../etc/ligand_dict.py
done

Para um iniciante como eu, aqui ZINC é uma parte do nome presente em todos os nomes de ligantes, portanto, deve ser mantido de acordo com o nome do seu ligante. Obrigado pelo seu tempo e meu amigo aqui que me ajudou apaixonadamente.

    
por 09.07.2016 / 13:09