Find the maximum of the lengths of all filenames in a directory

The name of the pictureThe name of the pictureThe name of the pictureClash Royale CLAN TAG#URR8PPP








up vote
1
down vote

favorite












I have to write a script that takes a directory name as an argument and writes to standard output the maximum of the lengths of all filenames in that directory. If the function’s argument is not a directory name, write an error message.



How can I do that










share|improve this question



















  • 4




    Welcome to Ask Ubuntu! You seem to be asking a "Give me a fish question". Both you and those who find your question later would be best served by a "How to Fish answer". You will likely get more focused answers if you edit your question to show what you have tried and where you are having trouble.
    – J. Starnes
    Feb 3 at 20:32











  • I am not seeing how this question is too broad... printing an error message if a condition is not met seems pretty reasonable to me! How would this benefit from being narrowed down?
    – Zanna
    Feb 5 at 22:33










  • What have you done already? Do you have an approach that you've already tried? Can you ask about a specific problem that you've had while trying this for yourself? If you haven't tried anything yet, then you're just asking someone on Ask Ubuntu to do work for you; that's not what the site is for.
    – Jeremy Kerr
    Feb 7 at 2:13














up vote
1
down vote

favorite












I have to write a script that takes a directory name as an argument and writes to standard output the maximum of the lengths of all filenames in that directory. If the function’s argument is not a directory name, write an error message.



How can I do that










share|improve this question



















  • 4




    Welcome to Ask Ubuntu! You seem to be asking a "Give me a fish question". Both you and those who find your question later would be best served by a "How to Fish answer". You will likely get more focused answers if you edit your question to show what you have tried and where you are having trouble.
    – J. Starnes
    Feb 3 at 20:32











  • I am not seeing how this question is too broad... printing an error message if a condition is not met seems pretty reasonable to me! How would this benefit from being narrowed down?
    – Zanna
    Feb 5 at 22:33










  • What have you done already? Do you have an approach that you've already tried? Can you ask about a specific problem that you've had while trying this for yourself? If you haven't tried anything yet, then you're just asking someone on Ask Ubuntu to do work for you; that's not what the site is for.
    – Jeremy Kerr
    Feb 7 at 2:13












up vote
1
down vote

favorite









up vote
1
down vote

favorite











I have to write a script that takes a directory name as an argument and writes to standard output the maximum of the lengths of all filenames in that directory. If the function’s argument is not a directory name, write an error message.



How can I do that










share|improve this question















I have to write a script that takes a directory name as an argument and writes to standard output the maximum of the lengths of all filenames in that directory. If the function’s argument is not a directory name, write an error message.



How can I do that







command-line scripts






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Feb 5 at 21:48









Zanna

48.3k13120229




48.3k13120229










asked Feb 3 at 20:12









MA VI

82




82







  • 4




    Welcome to Ask Ubuntu! You seem to be asking a "Give me a fish question". Both you and those who find your question later would be best served by a "How to Fish answer". You will likely get more focused answers if you edit your question to show what you have tried and where you are having trouble.
    – J. Starnes
    Feb 3 at 20:32











  • I am not seeing how this question is too broad... printing an error message if a condition is not met seems pretty reasonable to me! How would this benefit from being narrowed down?
    – Zanna
    Feb 5 at 22:33










  • What have you done already? Do you have an approach that you've already tried? Can you ask about a specific problem that you've had while trying this for yourself? If you haven't tried anything yet, then you're just asking someone on Ask Ubuntu to do work for you; that's not what the site is for.
    – Jeremy Kerr
    Feb 7 at 2:13












  • 4




    Welcome to Ask Ubuntu! You seem to be asking a "Give me a fish question". Both you and those who find your question later would be best served by a "How to Fish answer". You will likely get more focused answers if you edit your question to show what you have tried and where you are having trouble.
    – J. Starnes
    Feb 3 at 20:32











  • I am not seeing how this question is too broad... printing an error message if a condition is not met seems pretty reasonable to me! How would this benefit from being narrowed down?
    – Zanna
    Feb 5 at 22:33










  • What have you done already? Do you have an approach that you've already tried? Can you ask about a specific problem that you've had while trying this for yourself? If you haven't tried anything yet, then you're just asking someone on Ask Ubuntu to do work for you; that's not what the site is for.
    – Jeremy Kerr
    Feb 7 at 2:13







4




4




Welcome to Ask Ubuntu! You seem to be asking a "Give me a fish question". Both you and those who find your question later would be best served by a "How to Fish answer". You will likely get more focused answers if you edit your question to show what you have tried and where you are having trouble.
– J. Starnes
Feb 3 at 20:32





Welcome to Ask Ubuntu! You seem to be asking a "Give me a fish question". Both you and those who find your question later would be best served by a "How to Fish answer". You will likely get more focused answers if you edit your question to show what you have tried and where you are having trouble.
– J. Starnes
Feb 3 at 20:32













I am not seeing how this question is too broad... printing an error message if a condition is not met seems pretty reasonable to me! How would this benefit from being narrowed down?
– Zanna
Feb 5 at 22:33




I am not seeing how this question is too broad... printing an error message if a condition is not met seems pretty reasonable to me! How would this benefit from being narrowed down?
– Zanna
Feb 5 at 22:33












What have you done already? Do you have an approach that you've already tried? Can you ask about a specific problem that you've had while trying this for yourself? If you haven't tried anything yet, then you're just asking someone on Ask Ubuntu to do work for you; that's not what the site is for.
– Jeremy Kerr
Feb 7 at 2:13




What have you done already? Do you have an approach that you've already tried? Can you ask about a specific problem that you've had while trying this for yourself? If you haven't tried anything yet, then you're just asking someone on Ask Ubuntu to do work for you; that's not what the site is for.
– Jeremy Kerr
Feb 7 at 2:13










1 Answer
1






active

oldest

votes

















up vote
2
down vote



accepted










A script rather than a function. This prints the number of characters in the longest filename, which is what I understood you wanted:



#!/bin/bash

# include hidden files
shopt -s dotglob
# if the first argument is a directory
if [ -d "$1" ]; then
# move to that directory
cd "$1"
# set a variable to 0
long=0
# loop over all the files
for i in *; do
# print the filename - remove this line after testing
echo "$i"
# if the length of the current filename is longer
# than the value of the variable long, assign the
# length of the current filename to long
(( ($#i > $long) )) && long=$#i
done
# print the value of long
echo $long
# if the first argument wasn't a directory, print an error
else
printf "%sn" "Not a directory"
fi


This makes use of the dotglob setting, which causes globbing with * to include hidden files. To see the effect of it, run these commands in your home directory:



ls -d *
shopt -s dotglob
ls -d *


To turn off shopt settings, use -u for example shopt -u dotglob.



We need to check the argument is a directory, so we use if and the test command (in its [ form) which has a test for directories, -d:



if [ -d "$1" ]; then


this means, if the first argument passed to the script is the name of a directory that exists, then do the following. $1 is the first argument, and we enclose it in double quotes to stop the shell from performing further expansions on the value of the variable.



We need to go into the directory, because we need to get the length of the filename, not the whole path (absolute or relative). We don't want this:



$ for i in ~/*; do [ -d "$i" ] && echo "$i"; done
/home/zanna/custom
/home/zanna/Desktop
/home/zanna/Documents
/home/zanna/Downloads
...


because if we count the length of $i we will get the length of the full path. We could do some text processing antics (and maybe some cleverer tricks I don't know) to get rid of the path, but parsing filenames is generally unreliable and if we change directory we can easily get the shell to count characters for us using $#var to give the length of var (I believe that this counts characters and not bytes). Note that scripts run in a child shell, not in the current shell, so if a script changes directory, the working directory of the shell that calls the script isn't affected.



My script uses for to loop over the files in the directory. The line that does the work is



(( ($#i > $long) )) && long=$#i


This means, if the length of the current value of i is greater than the current value of long, then assign the length of i to long. Since we first set long to 0, the first filename will always be longer than long (because it's as short as possible). Thereafter, only the length of longer filenames will be able to replace the value of long. Since we know $#i and long will only contain integers, we don't need to protect them with double quotes. (( creates an arithmetic context in Bash so we can use > with its mathematical meaning (thanks to muru for pointing that out to me elsewhere).






share|improve this answer






















    Your Answer







    StackExchange.ready(function()
    var channelOptions =
    tags: "".split(" "),
    id: "89"
    ;
    initTagRenderer("".split(" "), "".split(" "), channelOptions);

    StackExchange.using("externalEditor", function()
    // Have to fire editor after snippets, if snippets enabled
    if (StackExchange.settings.snippets.snippetsEnabled)
    StackExchange.using("snippets", function()
    createEditor();
    );

    else
    createEditor();

    );

    function createEditor()
    StackExchange.prepareEditor(
    heartbeatType: 'answer',
    convertImagesToLinks: true,
    noModals: false,
    showLowRepImageUploadWarning: true,
    reputationToPostImages: 10,
    bindNavPrevention: true,
    postfix: "",
    onDemand: true,
    discardSelector: ".discard-answer"
    ,immediatelyShowMarkdownHelp:true
    );



    );













     

    draft saved


    draft discarded


















    StackExchange.ready(
    function ()
    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2faskubuntu.com%2fquestions%2f1002753%2ffind-the-maximum-of-the-lengths-of-all-filenames-in-a-directory%23new-answer', 'question_page');

    );

    Post as a guest






























    1 Answer
    1






    active

    oldest

    votes








    1 Answer
    1






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes








    up vote
    2
    down vote



    accepted










    A script rather than a function. This prints the number of characters in the longest filename, which is what I understood you wanted:



    #!/bin/bash

    # include hidden files
    shopt -s dotglob
    # if the first argument is a directory
    if [ -d "$1" ]; then
    # move to that directory
    cd "$1"
    # set a variable to 0
    long=0
    # loop over all the files
    for i in *; do
    # print the filename - remove this line after testing
    echo "$i"
    # if the length of the current filename is longer
    # than the value of the variable long, assign the
    # length of the current filename to long
    (( ($#i > $long) )) && long=$#i
    done
    # print the value of long
    echo $long
    # if the first argument wasn't a directory, print an error
    else
    printf "%sn" "Not a directory"
    fi


    This makes use of the dotglob setting, which causes globbing with * to include hidden files. To see the effect of it, run these commands in your home directory:



    ls -d *
    shopt -s dotglob
    ls -d *


    To turn off shopt settings, use -u for example shopt -u dotglob.



    We need to check the argument is a directory, so we use if and the test command (in its [ form) which has a test for directories, -d:



    if [ -d "$1" ]; then


    this means, if the first argument passed to the script is the name of a directory that exists, then do the following. $1 is the first argument, and we enclose it in double quotes to stop the shell from performing further expansions on the value of the variable.



    We need to go into the directory, because we need to get the length of the filename, not the whole path (absolute or relative). We don't want this:



    $ for i in ~/*; do [ -d "$i" ] && echo "$i"; done
    /home/zanna/custom
    /home/zanna/Desktop
    /home/zanna/Documents
    /home/zanna/Downloads
    ...


    because if we count the length of $i we will get the length of the full path. We could do some text processing antics (and maybe some cleverer tricks I don't know) to get rid of the path, but parsing filenames is generally unreliable and if we change directory we can easily get the shell to count characters for us using $#var to give the length of var (I believe that this counts characters and not bytes). Note that scripts run in a child shell, not in the current shell, so if a script changes directory, the working directory of the shell that calls the script isn't affected.



    My script uses for to loop over the files in the directory. The line that does the work is



    (( ($#i > $long) )) && long=$#i


    This means, if the length of the current value of i is greater than the current value of long, then assign the length of i to long. Since we first set long to 0, the first filename will always be longer than long (because it's as short as possible). Thereafter, only the length of longer filenames will be able to replace the value of long. Since we know $#i and long will only contain integers, we don't need to protect them with double quotes. (( creates an arithmetic context in Bash so we can use > with its mathematical meaning (thanks to muru for pointing that out to me elsewhere).






    share|improve this answer


























      up vote
      2
      down vote



      accepted










      A script rather than a function. This prints the number of characters in the longest filename, which is what I understood you wanted:



      #!/bin/bash

      # include hidden files
      shopt -s dotglob
      # if the first argument is a directory
      if [ -d "$1" ]; then
      # move to that directory
      cd "$1"
      # set a variable to 0
      long=0
      # loop over all the files
      for i in *; do
      # print the filename - remove this line after testing
      echo "$i"
      # if the length of the current filename is longer
      # than the value of the variable long, assign the
      # length of the current filename to long
      (( ($#i > $long) )) && long=$#i
      done
      # print the value of long
      echo $long
      # if the first argument wasn't a directory, print an error
      else
      printf "%sn" "Not a directory"
      fi


      This makes use of the dotglob setting, which causes globbing with * to include hidden files. To see the effect of it, run these commands in your home directory:



      ls -d *
      shopt -s dotglob
      ls -d *


      To turn off shopt settings, use -u for example shopt -u dotglob.



      We need to check the argument is a directory, so we use if and the test command (in its [ form) which has a test for directories, -d:



      if [ -d "$1" ]; then


      this means, if the first argument passed to the script is the name of a directory that exists, then do the following. $1 is the first argument, and we enclose it in double quotes to stop the shell from performing further expansions on the value of the variable.



      We need to go into the directory, because we need to get the length of the filename, not the whole path (absolute or relative). We don't want this:



      $ for i in ~/*; do [ -d "$i" ] && echo "$i"; done
      /home/zanna/custom
      /home/zanna/Desktop
      /home/zanna/Documents
      /home/zanna/Downloads
      ...


      because if we count the length of $i we will get the length of the full path. We could do some text processing antics (and maybe some cleverer tricks I don't know) to get rid of the path, but parsing filenames is generally unreliable and if we change directory we can easily get the shell to count characters for us using $#var to give the length of var (I believe that this counts characters and not bytes). Note that scripts run in a child shell, not in the current shell, so if a script changes directory, the working directory of the shell that calls the script isn't affected.



      My script uses for to loop over the files in the directory. The line that does the work is



      (( ($#i > $long) )) && long=$#i


      This means, if the length of the current value of i is greater than the current value of long, then assign the length of i to long. Since we first set long to 0, the first filename will always be longer than long (because it's as short as possible). Thereafter, only the length of longer filenames will be able to replace the value of long. Since we know $#i and long will only contain integers, we don't need to protect them with double quotes. (( creates an arithmetic context in Bash so we can use > with its mathematical meaning (thanks to muru for pointing that out to me elsewhere).






      share|improve this answer
























        up vote
        2
        down vote



        accepted







        up vote
        2
        down vote



        accepted






        A script rather than a function. This prints the number of characters in the longest filename, which is what I understood you wanted:



        #!/bin/bash

        # include hidden files
        shopt -s dotglob
        # if the first argument is a directory
        if [ -d "$1" ]; then
        # move to that directory
        cd "$1"
        # set a variable to 0
        long=0
        # loop over all the files
        for i in *; do
        # print the filename - remove this line after testing
        echo "$i"
        # if the length of the current filename is longer
        # than the value of the variable long, assign the
        # length of the current filename to long
        (( ($#i > $long) )) && long=$#i
        done
        # print the value of long
        echo $long
        # if the first argument wasn't a directory, print an error
        else
        printf "%sn" "Not a directory"
        fi


        This makes use of the dotglob setting, which causes globbing with * to include hidden files. To see the effect of it, run these commands in your home directory:



        ls -d *
        shopt -s dotglob
        ls -d *


        To turn off shopt settings, use -u for example shopt -u dotglob.



        We need to check the argument is a directory, so we use if and the test command (in its [ form) which has a test for directories, -d:



        if [ -d "$1" ]; then


        this means, if the first argument passed to the script is the name of a directory that exists, then do the following. $1 is the first argument, and we enclose it in double quotes to stop the shell from performing further expansions on the value of the variable.



        We need to go into the directory, because we need to get the length of the filename, not the whole path (absolute or relative). We don't want this:



        $ for i in ~/*; do [ -d "$i" ] && echo "$i"; done
        /home/zanna/custom
        /home/zanna/Desktop
        /home/zanna/Documents
        /home/zanna/Downloads
        ...


        because if we count the length of $i we will get the length of the full path. We could do some text processing antics (and maybe some cleverer tricks I don't know) to get rid of the path, but parsing filenames is generally unreliable and if we change directory we can easily get the shell to count characters for us using $#var to give the length of var (I believe that this counts characters and not bytes). Note that scripts run in a child shell, not in the current shell, so if a script changes directory, the working directory of the shell that calls the script isn't affected.



        My script uses for to loop over the files in the directory. The line that does the work is



        (( ($#i > $long) )) && long=$#i


        This means, if the length of the current value of i is greater than the current value of long, then assign the length of i to long. Since we first set long to 0, the first filename will always be longer than long (because it's as short as possible). Thereafter, only the length of longer filenames will be able to replace the value of long. Since we know $#i and long will only contain integers, we don't need to protect them with double quotes. (( creates an arithmetic context in Bash so we can use > with its mathematical meaning (thanks to muru for pointing that out to me elsewhere).






        share|improve this answer














        A script rather than a function. This prints the number of characters in the longest filename, which is what I understood you wanted:



        #!/bin/bash

        # include hidden files
        shopt -s dotglob
        # if the first argument is a directory
        if [ -d "$1" ]; then
        # move to that directory
        cd "$1"
        # set a variable to 0
        long=0
        # loop over all the files
        for i in *; do
        # print the filename - remove this line after testing
        echo "$i"
        # if the length of the current filename is longer
        # than the value of the variable long, assign the
        # length of the current filename to long
        (( ($#i > $long) )) && long=$#i
        done
        # print the value of long
        echo $long
        # if the first argument wasn't a directory, print an error
        else
        printf "%sn" "Not a directory"
        fi


        This makes use of the dotglob setting, which causes globbing with * to include hidden files. To see the effect of it, run these commands in your home directory:



        ls -d *
        shopt -s dotglob
        ls -d *


        To turn off shopt settings, use -u for example shopt -u dotglob.



        We need to check the argument is a directory, so we use if and the test command (in its [ form) which has a test for directories, -d:



        if [ -d "$1" ]; then


        this means, if the first argument passed to the script is the name of a directory that exists, then do the following. $1 is the first argument, and we enclose it in double quotes to stop the shell from performing further expansions on the value of the variable.



        We need to go into the directory, because we need to get the length of the filename, not the whole path (absolute or relative). We don't want this:



        $ for i in ~/*; do [ -d "$i" ] && echo "$i"; done
        /home/zanna/custom
        /home/zanna/Desktop
        /home/zanna/Documents
        /home/zanna/Downloads
        ...


        because if we count the length of $i we will get the length of the full path. We could do some text processing antics (and maybe some cleverer tricks I don't know) to get rid of the path, but parsing filenames is generally unreliable and if we change directory we can easily get the shell to count characters for us using $#var to give the length of var (I believe that this counts characters and not bytes). Note that scripts run in a child shell, not in the current shell, so if a script changes directory, the working directory of the shell that calls the script isn't affected.



        My script uses for to loop over the files in the directory. The line that does the work is



        (( ($#i > $long) )) && long=$#i


        This means, if the length of the current value of i is greater than the current value of long, then assign the length of i to long. Since we first set long to 0, the first filename will always be longer than long (because it's as short as possible). Thereafter, only the length of longer filenames will be able to replace the value of long. Since we know $#i and long will only contain integers, we don't need to protect them with double quotes. (( creates an arithmetic context in Bash so we can use > with its mathematical meaning (thanks to muru for pointing that out to me elsewhere).







        share|improve this answer














        share|improve this answer



        share|improve this answer








        edited Feb 15 at 19:15

























        answered Feb 5 at 22:28









        Zanna

        48.3k13120229




        48.3k13120229



























             

            draft saved


            draft discarded















































             


            draft saved


            draft discarded














            StackExchange.ready(
            function ()
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2faskubuntu.com%2fquestions%2f1002753%2ffind-the-maximum-of-the-lengths-of-all-filenames-in-a-directory%23new-answer', 'question_page');

            );

            Post as a guest













































































            Popular posts from this blog

            How do so many people here on Academia.SE, and in general, afford lavish higher education programs?

            Trouble downloading packages list due to a “Hash sum mismatch” error

            How do I move numbers in filenames, in a batch renaming operation?