Hjælp til for-loop og cp
Hej alle.
Jeg er ved at lave et script der kan gemme videoer fra fx Youtube på min computer.
Først findes programmets PID ved at køre
Dette gemmes i en variabel kaldet $PID
Selve filerne findes i /proc/$PID/fd, så for at finde alle flash-filer køres følgende:
Dette giver følgende output:
Her får jeg altså både navnet på filen i /proc (/proc/$PID/fd/17) samt filens originale sti (/tmp/FlashXXfPBaTM).
Problem:
Jeg kunne nu godt tænke mig at lave et for-loop, der tager output af file-kommandoen og indsætter det i en cp-kommando, så kommandoen kommer til at lyde:
Herunder er scriptet i dens nuværende stand, som kopierer filer direkte. Dvs. at den kopierer /proc/$PID/fd/17 til /tmp/17 og ikke /tmp/FlashXXfPBaTM som ønsket.
Jeg er ved at lave et script der kan gemme videoer fra fx Youtube på min computer.
Først findes programmets PID ved at køre
lsof | grep deleted | head -1 | awk '{ print $2 }'
Dette gemmes i en variabel kaldet $PID
Selve filerne findes i /proc/$PID/fd, så for at finde alle flash-filer køres følgende:
file $(find /proc/$PID/fd/ -print) | grep Flash | sort --u
Dette giver følgende output:
/proc/$PID/fd/17: broken symbolic link to `/tmp/FlashXXfPBaTM (deleted)'
Her får jeg altså både navnet på filen i /proc (/proc/$PID/fd/17) samt filens originale sti (/tmp/FlashXXfPBaTM).
Problem:
Jeg kunne nu godt tænke mig at lave et for-loop, der tager output af file-kommandoen og indsætter det i en cp-kommando, så kommandoen kommer til at lyde:
cp /proc/$PID/fd/17 /tmp/FlashXXfPBaTM
Herunder er scriptet i dens nuværende stand, som kopierer filer direkte. Dvs. at den kopierer /proc/$PID/fd/17 til /tmp/17 og ikke /tmp/FlashXXfPBaTM som ønsket.
PID=$(lsof | grep deleted | grep plugin-co | head -1 | awk '{ print $2 }')
for i in $(file $(find /proc/$PID/fd/ -print) | grep Flash | sort --u | awk '{ print $1 }' | sed 's/.$//')
do
echo "Now copying: $i to /tmp"
cp $i /tmp
echo "Done!"
done
Kommentarer8
Det er ikke for at være
Eller hvad med at bruge :
Jep, jeg kender godt til
Og nu har jeg altså valgt et problem, som jeg mener kan løses med et for-loop, som dog driller.
Men tak for inputtet, hvis jeg havde haft et "reelt" problem og bare skulle have en hurtig løsning, var det de helt rigtige svar:-)
okay... jeg undskylder, jeg
eksemple:
for i in $( ls ); do
echo item: $i
done
http://tldp.org/HOWTO/Bash-Prog-Intro-HOWTO-7.html
PID=$(lsof | grep deleted |
PID=$(lsof | grep deleted | grep plugin-co | head -1 | awk '{ print $2 }')
for i in $(file $(find /proc/$PID/fd/ -print) | grep Flash | sort --u | awk '{ print $1 }' | sed 's/.$//')
do
echo "Now copying: $i to /tmp"
cp $i /tmp
echo "Done!"
done
I sådan nogle tilfælde plejer jeg at bruge awk til at generere kommandolinjen og så pipe til shell'en (m.a.o: drop for-løkkerne).
Fx:
PID=$(lsof | grep deleted | grep plugin-co | head -1 | awk '{ print $2 }')
file $(find /proc/$PID/fd/ -print) | grep Flash | sort --u | sed -e 's/://g' -e 's/`//g' | awk '{ print "cp " $1 " " $6 }' | sh
Hvis du vil have den til at udskrive noget, så kan du jo udbygge awk-linjen efter bedste evne - fx:
file $(find /proc/$PID/fd/ -print) | grep Flash | sort --u | sed -e 's/://g' -e 's/`//g' | awk '{ print "printf \"Copying " $1 "...\""; print "cp " $1 " " $6 " && echo Done!"; }' | sh
Anyway, hvis du foretrækker for-loops, så burde det være muligt at tildele flere argumenter i stil med eksempel 11.2 her: http://tldp.org/LDP/abs/html/loops1.html . Jeg har dog ikke haft held med at få det til at virke.
Så fik jeg den næsten
Jeg har nu fået den til at kopiere en enkelt fil som jeg gerne vil have det, men modsat scriptet i min første post, begynder den ikke automatisk på næste fil.
Jeg går stærkt ud fra, at det har noget at gøre med, at jeg sætter gåseøjne (") omkring et flerlinjet output i dette stykke:
for i in "$(file $(find /proc/$PID/fd/ -print) | grep Flash | sort -u)";
I mit tilfælde ved jeg, at der ligger 3 flash-filer i /proc/$PID/fd/.
Her er scriptet som det ser ud nu:
#!/bin/bash
# Variables
PID=$(lsof | grep deleted | grep plugin-co | head -1 | awk '{ print $2 }')
COUNT=$(file $(find /proc/$PID/fd/ -print) | grep Flash | sort -u | wc -l)
# Script
echo "PID is $PID and we got $COUNT files to copy..."
for i in "$(file $(find /proc/$PID/fd/ -print) | grep Flash | sort -u)";
do
# Variables
PROC=$(echo $i | awk '{ print $1 }' | sed 's/.$//')
TMP=$(echo $i | awk '{ print $6 }' | cut -c2-)
# Commands
echo "Now copying: $PROC to $TMP"
cp $PROC $TMP
echo "Done!"
done
Jeg går stærkt ud fra, at
Jeg går stærkt ud fra, at det har noget at gøre med, at jeg sætter gåseøjne (") omkring et flerlinjet output i dette stykke:
Ja, præcis. Løkken afvikles kun en enkelt gang, så (prøv at echo $i for at se om den indeholder multiple linjer når der er flere filer).
Så du mit indlæg #5 inden du skrev?
(prøv at echo $i for at se
Jeg har før kørt echo $i, hvilket bekræfter min hypotese om at den indeholder flere linjer.
Min modifikation af din kommando-linje ser således ud:
#!/bin/bash
# Variables
PID=$(lsof | grep deleted | grep plugin-co | head -1 | awk '{ print $2 }')
COUNT=$(file $(find /proc/$PID/fd/ -print) | grep Flash | sort -u | wc -l)
# Script
echo "PID is $PID and we have $COUNT files to copy..."
file $(find /proc/$PID/fd/ -print) | grep Flash | sort -u | sed -e 's/://g' -e 's/`//g' | awk '{ print "printf \"Copying " $1 " to " $6 "...\""; print "cp " $1 " " $6 " && echo Done!"; }' | sh
echo "Done copying $COUNT files."