obtenir juste l'entier de wc dans bash

115

Existe-t-il un moyen d'obtenir l'entier que wc renvoie dans bash?

Fondamentalement, je veux écrire les numéros de ligne et le nombre de mots à l'écran après le nom du fichier.

output: filename linecount wordcount Voici ce que j'ai jusqu'à présent:

files=`ls`
for f in $files;
do
        if [ ! -d $f ] #only print out information about files !directories
        then
                # some way of getting the wc integers into shell variables and then printing them
                echo "$f $lines $ words"
        fi
done

Jordan
la source

Réponses:

57

Vous pouvez utiliser la cutcommande pour obtenir uniquement le premier mot de wcla sortie de (qui est le nombre de lignes ou de mots):

lines=`wc -l $f | cut -f1 -d' '`
words=`wc -w $f | cut -f1 -d' '`
casablanca
la source
5
Exécuter wc deux fois pour le même fichier est inefficace.
gawi
3
C'est vrai, c'est pourquoi je pense que la réponse de James Broadhead est bien meilleure. Je n'ai pas pu cuttravailler sur la sortie complète de wc $fparce que le nombre d'espaces entre les champs varie.
casablanca
1
@casablanca Vous pouvez réduire le nombre d'espaces en utilisant «tr -s». J'ai répertorié des solutions plus portables à cette question dans ma réponse ci-dessous.
rouble
Puisque dans cette réponse, nous attribuons à une variable, nous pourrions tuer les espaces avec
cycollins
88

La réponse la plus simple qui soit:

wc < filename 
BananeNeil
la source
5
Mais ne produit pas la sortie souhaitée.
Dave Newton
bien sûr, il vous suffit de transmettre les paramètres appropriés que vous feriez de toute façon. par exemple, si vous le faites wc -c < file name, cela ne vous donnera que le nombre entier d'octets et rien d'autre.
BananaNeil
13
Mon point était que si vous allez répondre à une question (vieille de 1,5 an), autant mettre toutes les informations dans la réponse, c'est tout :)
Dave Newton
oups, relisez la question .. #fail, je cherchais comment obtenir uniquement les nombres entiers, et j'utilisais les informations de l'une des réponses, quand j'ai découvert une meilleure réponse, puis j'ai décidé de poster à ce sujet. désolé ..
BananaNeil
3
Vous avez répondu à Google, c'est ce qui compte. :-)
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功
82

Juste:

wc -l < file_name

fera le travail. Mais cette sortie inclut des espaces blancs préfixés comme wcalignant à droite le nombre.

sten
la source
3
Pour obtenir juste le nombre de lignes sans espace: wc -l < foo.txt | xargsref - stackoverflow.com/a/12973694/149428
Taylor Edmiston
1
Ainsi, alors que la commande produit une réponse avec des espaces de début, le questionneur affectait une variable et cela supprime automatiquement les espaces de début (du moins c'était mon expérience sur l'ancien OSX bash). En d'autres termes, il en lines=`wc -l < $f`résulte une variable "ligne" dont la valeur n'a pas d'espaces de début.
cycollins
Et si je joue avec Find? J'obtiens une erreur: find . -path -prune -o -name "*.swift" -print0 | xargs -0 wc -lfonctionne bien mais imprime chaque fichier. Si j'utilise, find . -path -prune -o -name "*.swift" -print0 | xargs -0 wc -l <j'obtiens une erreur. parse error near '\n'
Nuno Gonçalves
55
wc $file | awk {'print "$4" "$2" "$1"'}

Ajustez si nécessaire pour votre mise en page.

Il est également plus agréable d'utiliser la logique positive ("est un fichier") plutôt que le négatif ("pas un répertoire")

[ -f $file ] && wc $file | awk {'print "$4" "$2" "$1"'}
James Broadhead
la source
1
Sur mon Windows dans Cmder (bash 4.4.12) cela fonctionne: wc $file | awk '{print $4" "$2" "$1}'- apostrophes en dehors de {}.
Grzegorz Gierlik
36

Parfois, wc sort dans différents formats sur différentes plates-formes. Par exemple:

Sous OS X:

$ echo aa | wc -l

         1

En Centos:

$ echo aa | wc -l

1

Ainsi, n'utiliser que couper peut ne pas récupérer le numéro. Essayez plutôt de supprimer les caractères d'espacement:

$ echo aa | wc -l | tr -d ' '
Tahsin Turkoz
la source
23

Les réponses acceptées / populaires ne fonctionnent pas sous OSX.

Tous les éléments suivants doivent être portables sur bsd et linux.

wc -l < "$f" | tr -d ' '

OU

wc -l "$f" | tr -s ' ' | cut -d ' ' -f 2

OU

wc -l "$f" | awk '{print $1}'
rouble
la source
11

Si vous redirigez le nom de fichier, wcil omet le nom de fichier à la sortie.

Frapper:

read lines words characters <<< $(wc < filename)

ou

read lines words characters <<EOF
$(wc < filename)
EOF

Au lieu d'utiliser forpour itérer sur la sortie de ls, faites ceci:

for f in *

qui fonctionnera s'il y a des noms de fichiers qui incluent des espaces.

Si vous ne pouvez pas utiliser de globulation, vous devez diriger dans une while readboucle:

find ... | while read -r f

ou utilisez la substitution de processus

while read -r f
do
    something
done < <(find ...)
Suspendu jusqu'à nouvel ordre.
la source
Je vous ai quand même augmenté, mais vous n'avez pas besoin de rediriger le nom du fichier. Capturez-le simplement comme un champ supplémentaire. read lines words characters filename <<< $(wc "$f")Oh, et si vous étiez * pour être durci contre les espaces, vous voulez également double guillemet la var lorsque vous l'utilisez.
Bruno Bronosky
Utiliser une variable supplémentaire est en effet une autre façon de le faire, mais si vous n'utilisez pas la variable (peut-être que vous avez déjà le nom de fichier dans une variable - $fdans ce cas), ce n'est pas nécessaire. En outre, l'OP a demandé comment obtenir uniquement l'entier. Vous avez raison de citer une variable, mais je n'ai pas montré l'utilisation de la variable, j'ai donc omis de mentionner ce point. Le for f in *formulaire devrait presque toujours être utilisé au lieu d'utiliser la sortie de ls, comme vous le savez.
Suspendu jusqu'à nouvel ordre.
Je suis entièrement d'accord sur ce lspoint. Cela vous rapportera un prix. partmaps.org/era/unix/award.html#ls
Bruno Bronosky
Si vous ne voulez pas le nom du fichier, vous pouvez faire ceci:read lines words characters _ <<< $(wc "$f")
@EvanTeitelman: Comme discuté dans quelques commentaires ci-dessus le vôtre. $_est juste une variable différente.
Suspendu jusqu'à nouvel ordre.
3

Si le fichier est petit, vous pouvez vous permettre d'appeler wcdeux fois et utiliser quelque chose comme ce qui suit, ce qui évite de passer à un processus supplémentaire:

lines=$((`wc -l "$f"`))
words=$((`wc -w "$f"`))

Le $((...))est l' expansion arithmétique de bash. Il supprime tous les espaces de la sortie de wcdans ce cas.

Cette solution est plus logique si vous avez besoin soit le linecount ou le wordcount.

Walter Tross
la source
2

Et avec sed?

wc -l /path/to/file.ext | sed 's/ *\([0-9]* \).*/\1/'
mgold
la source
1
typeset -i a=$(wc -l fileName.dat  | xargs echo | cut -d' ' -f1)
GeorgesMakarios
la source
1

Essayez ceci pour le résultat numérique:
nlines = $ (wc -l <$ myfile)

Paulonki
la source
0

Essaye ça:

wc `ls` | awk '{ LINE += $1; WC += $2 } END { print "lines: " LINE  " words: " WC }'

Il crée un nombre de lignes et un nombre de mots (LINE et WC), et les augmente avec les valeurs extraites de wc (en utilisant 1 $ pour la valeur de la première colonne et 2 $ pour la seconde) et imprime enfin les résultats.

Aif
la source
0

"Fondamentalement, je veux écrire les numéros de ligne et le nombre de mots à l'écran après le nom du fichier."

answer=(`wc $f`)
echo -e"${answer[3]}
lines:  ${answer[0]}
words:  ${answer[1]}
bytes:  ${answer[2]}"

Sorties: myfile.txt lignes: 10 mots: 20 octets: 120

user8155253
la source
0
files=`ls`
echo "$files" | wc -l | perl -pe "s#^\s+##"
Pedro Reis
la source
Si vous utilisez perlquand même, autant faire le décompte des mots en Perl. Une approche plus économique serait de canaliser verstr -d '[:space:]'
tripleee