Exécution d'un script sur une liste de fichiers

Aug 23 2020

J'ai un script qui obtient un fichier .vcf, analyse cela et l'écrit dans un .txt

grep -v "#" file.vcf | sed 's/chrM/MT/' | sed 's/chrX/X/' | sed 's/chrY/Y/' | awk '{print $1,$2,$2,$4"/"$5,"+"}' | sed 's/chr//g' > vcf_output.txt

J'ai 27 .vcffichiers sur lesquels je veux exécuter ce script en même temps et écrire la sortie de chacun .vcfdans un .txtfichier du nom de celui-ci.vcf

J'ai trouvé ceci dans Google mais rien ne se passe après avoir exécuté cela

for f in *.vcf; do
    script "$f" > "${f%.*}.txt"
done

J'ai adopté ça comme ci-dessous

for f in *.vcf; do

grep -v "#" | sed 's/chrM/MT/' | sed 's/chrX/X/' | sed 's/chrY/Y/' | awk '{print $1,$2,$2,$4"/"$5,"+"}' | sed 's/chr//g' "$f" > "${f%.*}.txt"
    done

J'ai aussi essayé ça

(base) loan-mac-13:Pre_Treatment fi1d18$ find -type f -name "*.vcf" | xargs grep -v "#" | sed 's/chrM/MT/' | sed 's/chrX/X/' | sed 's/chrY/Y/' | awk '{print $1,$2,$2,$4"/"$5,"+"}' | sed 's/chr//g' "$f" > "${f%.*}.txt"
find: illegal option -- t
usage: find [-H | -L | -P] [-EXdsx] [-f path] path ... [expression]
       find [-H | -L | -P] [-EXdsx] -f path [path ...] [expression]
sed: : No such file or directory
(base) loan-mac-13:Pre_Treatment fi1d18$ 

Comment puis-je faire en sorte que cela fonctionne pour moi?

Réponses

EdMorton Aug 23 2020 at 20:05

Vous avez converti script "$f"votre sortie google en grep -v "#"(c'est- à -dire qu'il manque le "$f") dans votre script de boucle shell, puis vous l'utilisez à la "$f"place {}et vous l'utilisez au mauvais endroit dans votre xargsscript.

De toute façon, vous n'avez jamais besoin d'un tas de seds et de greps dans une pipleine lorsque vous utilisez awk. Vous n'avez fourni aucun exemple d'entrée / sortie, donc le script awk suivant n'est qu'une traduction directe de votre pipeline existant et il existe probablement une meilleure façon de l'écrire, mais ce script awk est tout ce dont vous avez besoin, pas de boucles shell ou autre :

awk '
    FNR == 1 {
        close(out)
        out = FILENAME
        sub(/\.vcf$/,".txt",out)
    }
    !/#/ {
        sub(/chrM/,"MT")
        sub(/chrX/,"X")
        sub(/chrY/,"Y")
        $0 = $1 OFS $2 OFS $2 OFS $4 "/" $5 OFS "+"
        gsub(/chr/,"")
        print > out
    }
' *.vcf

Si vous voulez l'entasser sur moins de lignes comme vous l'avez fait avec votre pipeline grep + seds + awk, vous pouvez simplement utiliser des points-virgules partout où il y a une nouvelle ligne dont vous voulez vous débarrasser sauf après chacune {, par exemple:

awk 'FNR==1{close(out); out=FILENAME; sub(/\.vcf$/,".txt",out)} !/#/{sub(/chrM/,"MT"); sub(/chrX/,"X"); sub(/chrY/,"Y"); $0=$1 OFS $2 OFS $2 OFS $4 "/" $5 OFS "+"; gsub(/chr/,""); print > out}' *.vcf
xddq Aug 23 2020 at 08:48

Vous pouvez utiliser find et xargs pour cela.

Find listera tous les fichiers.

find -type f -name "*.vcf"

Avec xargs nous pouvons opérer sur chaque fichier trouvé.

find -type f -name "*.vcf" | xargs grep -v "#" | sed 's/chrM/MT/' | sed 's/chrX/X/' | sed 's/chrY/Y/' | awk '{print $1,$2,$2,$4"/"$5,"+"}' | sed 's/chr//g' "$f" > "${f%.*}.txt"

devrait faire le travail?

salutations

RakeshSharma Aug 23 2020 at 13:42

Sans altérer aucun de votre flux, ce qui suit devrait fonctionner. Notez que vous n'avez rien entré dans la première commande grep du pipeline. Donc rien ne bougeait.

for f in *.vcf; do

< "$f"  grep -v "#" | sed 's/chrM/MT/' | sed 's/chrX/X/' | sed 's/chrY/Y/' | awk '{print $1,$2,$2,$4"/"$5,"+"}' | sed 's/chr//g'  > "${f%.*}.txt"
    done