The Creators of Disney’s Kiff Share Their Inspirations for the New Animated Series

https://i.kinja-img.com/gawker-media/image/upload/c_fill,f_auto,fl_progressive,g_center,h_675,pg_1,q_80,w_1200/291569868a92322d62f32999bfb7f4ed.jpg

A new buddy comedy is coming to the Disney Channel and Disney+. Inspired by animated favorites like The Simpsons and DuckTales, Kiff is a new generation’s slice-of-life series in which—surrounded by friends and family in an eccentric community—two friends find adventures just around the corner.

io9 recently sat down with Kiff creators Nic Smal and Lucy Heavens to chat about the show. It centers on a spunky squirrel protagonist and her laid-back bunny bestie Barry, and takes inspiration from the people and places Smal and Heavens encountered when they were growing up.


Best Friends Forever! | Kiff | NEW Series! | Kiff a NEW @disneychannel Cartoon

Sabina Graves, io9: I’m excited to chat with you all about Kiff. I’ve watched a few of the episodes. I think it’s so bonkers and silly. I loved it. Can you tell me a bit about the inspiration for the show, and how you all collaborated on this concept?

Heavens: Thank you! We really just wanted to do a project that we would be filled with joy to make and that we wanted to watch. We had this the sort of kernel of what Kiff was in terms of her character and her personality, and we kind of spun it out from there—we just leaned on all of our favorite people and places, and it’s a very relatable show. And yeah, it was just all things that made us laugh.

Smal: We made it to the studio and we sort of clicked on similar kind of tastes in comedy and we had fun chatting about it. And I drew Kiff, which at the time was just like a big light bulb. And we both sat there and just were like: “heheheheheh.” Just the world started showing itself to us from there. It just all spun out from Kiff.

G/O Media may get a commission

io9: That’s awesome. I love how Kiff has this really big sense of go-getter adventurer attitude, and a lot of times her imagination plays out scenarios and how she thinks it should go. It’s really cool to show audiences that things aren’t always going to go as you imagine them. What was important to you in showing your audience how to navigate life when things don’t go as planned?

Heavens: I think maybe if anything, the show is like “life doesn’t go the way that you think it will.” And it’s a kind of “know thyself” show, where you look at your behavior and what motivated you and you understand yourself a bit better.

Smal: Yeah, and even if things don’t kind of turn out or pan out exactly how you imagined it, whatever kind of twists and turns happen—if you got someone you know by your side that you care for deeply and cares for you and is nonjudgmental, just the pure friendship and support, then anything’s possible. And that’s all that really matters. You know?

io9: For sure. I think anyone could use a Barry [Kiff’s bunny bestie]. I love the the family episode where Kiff gets to be an honorary member of Barry’s family, because there’s always that funny dynamic of how your family acts one way when it’s just family, and then when guests are over, it’s kind of different…

Smal: And that that feeling going over to someone’s house for the first time for a sleepover and feeling a bit like there is a difference. What’s normal to one family might be completely, wildly, not normal to another, but it’s like, “Hey, it’s all good.”

io9: It’s like such a fun dynamic to see Kiff meld into. I also had a really good time with the road trip—it kind of gave me Fury Road, Mad Max vibes. There’s certainly pop culture touchstones that stand out, like the Kill Bill noise.

Heavens: We do love and pay homage to all things popular culture.

io9: What your first fandoms in animation, and how did they inform your career path?

Heavens: It was The Simpsons—ain’t it just the way as a millennial?

Smal: We didn’t know each other at that age, but we both were recording The Simpsons on VHS, creating our own collections.

Heavens: “Do not tape over.”

Smal: Cartoons were just something that I always felt there was a connection there, and always comedy. The afternoons just spent watching back-to-back whatever was coming on. I think animation really comes and finds you. Shows like SpongeBob SquarePants and DuckTales.

Heavens: And Animaniacs.

io9: I mean, yeah.

Heavens: We both just ate it all up. But probably in terms of sensibility, [and] in terms of what informed our sense of humor, it is probably mostly The Simpsons.

io9: The world-building of the different people in Kiff’s life definitely has that [Simpsons] feel, like they each have a sense of their own inner life. When it came to creating that, were the voices for these characters on the page, or did you open it up to some of the voice talent to really make it their own as well?

Heavens: It’s a kind of endless feedback loop, where we started with the voice on the page, and then we were getting it back, and then you write more for that voice, and then there are elements that you really enjoy—and on it goes. That’s been a very happy part of the process.


Kiff premieres Friday, March 10, on the Disney Channel (8:00 p.m. EST/PST), and will drop on on Disney+ streaming right after.


Want more io9 news? Check out when to expect the latest Marvel, Star Wars, and Star Trek releases, what’s next for the DC Universe on film and TV, and everything you need to know about the future of Doctor Who.

Gizmodo

Seven Tips to Learn Laravel More Effectively

https://twtv3.ams3.digitaloceanspaces.com/posts/90455478bb71b5642dccd5bbbac98350.jpeg

When it comes to creating online apps, Laravel is a go-to PHP framework. It has many vital features that allow developers to construct websites quickly and easily. It’s also highly fluid, user-friendly, and simple to pick up and grasp and put into practice. 

Many resources are available to assist you in learning Laravel as the community grows. What’s more, how do you decide which is the best? Is there a method of learning that is more suited to your needs?

Here are seven tips to learn Lavarel more efficiently. 

Start with Official Documents

Laravel’s official documentation is a common initial step for novices. No offence to Laravel’s docs, but don’t get me wrong! Documentation writers often assume their audience is familiar with PHP and its associated technologies before they begin writing it.

Installation, for example, does not simply consist of “download and install.” Composer, the terminal, the command line, and setting up a Web server are all necessary skills.

Learn About Different Systems

Secondly, familiarize yourself with the Modal, View, & Controller (MVC) architecture before using Laravel. If you don’t know MVC, you won’t grasp Laravel and its terminology.

Work on Composer

Composer is a PHP dependency management; learn how to utilize it. There is no need to keep track of every one of the libraries and dependencies necessary for the project. To get started with Laravel, you’ll first need to have Composer installed and then install some of its dependencies on your own.

Use Different Sources

One of the most common questions is, “How do I get started?” People’s preferences differ from one another. Reading books or watching instructional videos are two standard learning methods, and each has its pros and cons. Both options are good.

However, it would help if you were on the lookout for anything with good structure and stability. The results you’re looking for won’t come from YouTube or some other random source. Writing consistency is essential. If you don’t, you risk becoming lost and not following through with the rest of the classes.

Also Read: Top 10 reasons to choose Laravel

Try Routing

The core of every Laravel-based online application is routing. When users learn that Laravel does not automate HTTP queries, they panic. Routing in and out of HTTP requests is taken care of by Laravel’s routes file. Laravel’s routing mechanism may be understood if you are acquainted with HTTP techniques.

Focus on Creating

It is crucial to concentrate on creating rather than watching and reading videos if you want to be known in coding. Start coding as soon as possible. After you complete your session, I recommend practising the codes. Moreover, I suggest you take a test at the end of each chapter to improve your morale and help you identify areas of weakness.

Seek a Role Model

When you’re beginning to program, the most challenging part is figuring out how to fix things when they don’t function. Asking for assistance is the best course of action in this situation. Finding a deity who can aid you is essential!

To locate a mentor, where should you look? In both your natural and online social circles. They’ll be more than delighted to assist you if they’re not too busy and your query isn’t ridiculous. See if you can track down the person you’re looking for and then send them a note.

Laravel News Links

MySQL: Selecting random rows

Given a table named tbl with one million entries, we want to select a random row from this table, fast.
Our table definition looks like this:

create table tbl (
 id INTEGER NOT NULL,
 d VARCHAR(200) NOT NULL,
 INDEX(id)
);


Dense id space

We can generate some test data using a recursive CTE:

mysql> set cte_max_recursion_depth = 100000;
mysql> insert into tbl  -> with recursive c(n, u) as (
 -> select 1, uuid()  -> union all
 -> select n+1, uuid() from c where n < 100000
 -> ) select * from c ;

The Recursive CTE will generate 100k pairs of (number, uuid()).
The initial row is defined in the upper row of the UNION, each subsequent row builds recursively on top of that, by simply counting up.

Since we generate all the values in one transaction, the uuid() is actually static.
That is, because inside a transaction time stops, and the uuid is internally time-based.

Since the id-space is free of gaps, we have rng many numbers between min(id) as min and max(id) as max.
Using the index on id, we can simply generate a random number between these boundaries and select the row.

mysql> select min(id), max(id) into @min, @max from tbl;
mysql> select @max-@min+1 into @rng;

mysql> select * from tbl where id = floor(rand() * @rng) + @min;
+-------+--------------------------------------+
| id | d |
+-------+--------------------------------------+
| 79720 | 13b94bdf-bc1c-11ed-9c65-08606ee5ff82 |
+-------+--------------------------------------+
1 row in set (0.06 sec)

mysql> select * from tbl where id = floor(rand() * @rng) + @min;
+-------+--------------------------------------+
| id | d |
+-------+--------------------------------------+
| 28379 | 13b64d6a-bc1c-11ed-9c65-08606ee5ff82 |
+-------+--------------------------------------+
1 row in set (0.06 sec)


Gaps, and we don’t care

If our table has gaps, and we do not care, we can simply move to an inequality and work with that:

mysql> select floor(rand() * @rng) + @min into @val;

mysql> > select @val, tbl.* from tbl where id >= @val limit 1;
+-------+-------+--------------------------------------+
| @val | id | d |
+-------+-------+--------------------------------------+
| 46346 | 46346 | 13b74a19-bc1c-11ed-9c65-08606ee5ff82 |
+-------+-------+--------------------------------------+
1 row in set (0.00 sec)

mysql> delete from tbl where id % 2 = 0;
Query OK, 50000 rows affected (0.71 sec)

mysql> select @val, tbl.* from tbl where id
>= @val limit 1;
+-------+-------+--------------------------------------+
| @val | id | d |
+-------+-------+--------------------------------------+
| 46346 | 46347 | 13b74a1c-bc1c-11ed-9c65-08606ee5ff82 |
+-------+-------+--------------------------------------+
1 row in set (0.00 sec)


Generating truly random rows

Using Python, we can generate truly random rows.

def generate(count = 1000000):
 """ Generate some test data """
 sqlcmd = "insert into tbl (id, d) values ( %(id)s, %(d)s )"

 # ID values with a step of 100, in random order
  # this ues a lot of memory to materialize the list
 id_list = [ i for i in range(0, count * 100, 100 )]
 # but if we want to shuffle, we have hardly any other option 
 random.shuffle(id_list)

 counter = 0
 data = []

 # Write them out, in batches of 1000.
 for i in id_list:
 item = {"id": i, "d": uuid.uuid4()}
 data.append(item)
 counter += 1

 if (counter % 1000) == 0:
 try:
 c = db.cursor()
 c.executemany(sqlcmd, data)
 except MySQLdb.Error as e:
 print(f"MySQL Error: {e}", file=sys.stderr)
 sys.exit()

 data = []
 db.commit()

 db.commit()

and that yields

mysql> select * from tbl limit 10;
+----------+--------------------------------------+
| id | d |
+----------+--------------------------------------+
| 720800 | d6aba075-d30c-4159-a3f9-67e23ac5674e |
| 2548500 | 18fccfa2-4fc6-4642-861b-4c98314cd6f1 |
| 86144900 | e5a58428-c5e1-4a32-a009-88b5877348bf |
| 88949600 | fabbce25-221e-41d3-97e4-8cfa6bdc4816 |
| 18642300 | 6df95b85-0d49-487c-98b0-548980479e16 |
| 59352400 | 4dfa8a3c-95e7-41b6-83f4-1f1c9f647ecd |
| 11149400 | 60d19e1f-1bca-41d2-93a6-1f9af585bbd4 |
| 37822800 | eebeafd8-b08a-483d-88a5-f779de5d6888 |
| 88126400 | 04c4d0ed-ba7c-456f-ac8c-a72448f38621 |
| 65363500 | 876794c9-b3b5-4cda-9acd-dacb4f5a9419 |
+----------+--------------------------------------+
10 rows in set (0.00 sec)

If we had defined the table with a primary key, InnoDB would have kept the data in primary key order – sorted by id.
Since we did not, the output is kept in generative order.


Window functions do not help us here

We can generate row numbers, using window functions:

mysql> select tbl.*, row_number() over () as r from tbl limit 10;
+----------+--------------------------------------+----+
| id | d | r |
+----------+--------------------------------------+----+
| 720800 | d6aba075-d30c-4159-a3f9-67e23ac5674e | 1 |
| 2548500 | 18fccfa2-4fc6-4642-861b-4c98314cd6f1 | 2 |
| 86144900 | e5a58428-c5e1-4a32-a009-88b5877348bf | 3 |
| 88949600 | fabbce25-221e-41d3-97e4-8cfa6bdc4816 | 4 |
| 18642300 | 6df95b85-0d49-487c-98b0-548980479e16 | 5 |
| 59352400 | 4dfa8a3c-95e7-41b6-83f4-1f1c9f647ecd | 6 |
| 11149400 | 60d19e1f-1bca-41d2-93a6-1f9af585bbd4 | 7 |
| 37822800 | eebeafd8-b08a-483d-88a5-f779de5d6888 | 8 |
| 88126400 | 04c4d0ed-ba7c-456f-ac8c-a72448f38621 | 9 |
| 65363500 | 876794c9-b3b5-4cda-9acd-dacb4f5a9419 | 10 |
+----------+--------------------------------------+----+
10 rows in set (0.00 sec)

But since they are generated on the fly, they are not an efficient way to select a random row:
We cannot use Window functions in any interesting context, and using them in a subquery basically forces the database to materialize all the rows before the one we are interested in.
So this is slow:

mysql> select tbl.*, row_number() over () as r from tbl where r = 192383;
ERROR 1054 (42S22): Unknown column 'r' in 'where clause'

mysql> select tbl.*, row_number() over () as r from tbl where row_number() over () = 192383;
ERROR 3593 (HY000): You cannot use the window function 'row_number' in this context.

mysql> select tbl.*, row_number() over () as r from tbl having r = 192383;
ERROR 3594 (HY000): You cannot use the alias 'r' of an expression containing a window function in this context.

mysql> select * from ( select tbl.*, row_number() over () as r from tbl ) as t where r = 192383;
+----------+--------------------------------------+--------+
| id | d | r |
+----------+--------------------------------------+--------+
| 85856500 | 17e04a8a-95e5-4f5f-8aa2-597c2d37dd43 | 192383 |
+----------+--------------------------------------+--------+
1 row in set (4.58 sec)


Selecting randomly from tables with gaps

Without continuous ids, and without a row count we cannot easily select the “n-th record” from a table.
So the best we can do is to select all id-values, and shuffle them, then choose the first row from the shuffle:

mysql> select id from tbl order by rand() limit 1;
+----------+
| id |
+----------+
| 64527400 |
+----------+
1 row in set (0.86 sec)

We can turn this into a full row with a join with almost no cost:

mysql> select * from tbl as t1  -> join (
 -> select id from tbl order by rand() limit 1
 -> ) as t2 on t1.id = t2.id;
+----------+--------------------------------------+----------+
| id | d | id |
+----------+--------------------------------------+----------+
| 24765800 | dcabd753-a357-4f38-a255-e81b0675654f | 24765800 |
+----------+--------------------------------------+----------+
1 row in set (0.82 sec)


Consuming rows

In the previous examples, we have been re-ordering the table randomly for each access (or group of accesses).
The shuffle has not been made persistent.

Often, the problem is not to select a random row, but to consume rows in random order.
We can store a random number with each row, and then use this as an (indexed) ordering key.
Using the knowledge from
the queueing article
,
we can select the item with the highest ordering value, lock it for consumption, retrieve it and delete it.

The idea is to add a column ordering to our table, indexed for fast access.
The ordering value is assigned randomly.
Here, we are creating the values after the fact in batch for one million entries, but in a system you would probably do that for each item as you write the item.

mysql> alter table tbl add column ordering double, add index(ordering);
Query OK, 0 rows affected (20.18 sec)
Records: 0 Duplicates: 0 Warnings: 0

mysql> update tbl set ordering = rand();
Query OK, 1000000 rows affected (1 min 8.27 sec)
Rows matched: 1000000 Changed: 1000000 Warnings: 0

To consume a random row, we start a transaction, select the row we want, using FOR UPDATE and SKIP LOCKED, and then delete it.

mysql> START TRANSACTION;

-- Two rows with the same ordering value may exist.
-- We can distinguish them by id, and can process one or both of them.
--
-- If another process has a lock on the topmost row, we will get zero results
-- due to the use of SKIP LOCKED.
mysql> select * from tbl where ordering = (select max(ordering) from tbl) for update skip locked;
+----------+--------------------------------------+--------------------+
| id | d | ordering |
+----------+--------------------------------------+--------------------+
| 31106100 | dc12e901-64a0-45a1-8f2e-dee93e3c8ab9 | 0.9999995017424221 |
+----------+--------------------------------------+--------------------+
1 row in set (0.00 sec)

mysql> delete from tbl where id = 31106100;
Query OK, 1 row affected (0.00 sec)

mysql> commit;
<actual processing outside of the transaction>

Here, the inner query determines the maximum “ordering” value, which is fast due to the index.
We make use of that value to fetch “a row”.
Nothing prevents multiple rows from matching, so we may get one or more rows.
We take the first (or all values), process it, and delete the processed rows, then commit.

Because we use FOR UPDATE, each row we select will also be exclusively locked, so other consumers cannot touch them.
Because of the SKIP LOCKED, other consumers will not be hanging on locked rows.
Instead, they will simply not see locked rows, so our query may actually even return zero rows in a concurrent context.

Alternatively, you do not strictly process items in order, and want to process them “roughly” in order, but be able to leverage multiple consumers.
A query such as the one below selects one or more items to process (locking them), so that they can be picked up for processing and deleted.

mysql> start transaction read write;

-- This is the first UNLOCKED row available for processing.
--
-- Another process may have a lock on another row with an even larger ordering value,
-- but thanks to SKIP LOCKED, we will not see that. mysql> select * from tbl order by ordering desc limit 1 for update skip locked;
+----------+--------------------------------------+--------------------+
| id | d | ordering |
+----------+--------------------------------------+--------------------+
| 68998800 | bcf7cca2-076d-444b-922b-ae064a1c49a8 | 0.9999983534216865 |
+----------+--------------------------------------+--------------------+
1 row in set (0.00 sec)

mysql> delete from tbl where id = 68998800;
Query OK, 1 row affected (0.00 sec)

mysql> commit;

<actual processing outside of the transaction>

For scalability, it is important to keep the interval between START TRANSACTION and COMMIT as short as possible.
Therefore, it is advisable to keep the actual item processing outside the transaction.

Because we do not need to shuffle things each time when we access things, this is actually much faster than “selecting a random row”.

Planet MySQL

Plastic Cup Machine

http://img.youtube.com/vi/amlg8O6YS4g/0.jpg

Plastic Cup Machine

Link

Disposable plastic cups aren’t exactly the best thing for the environment. Still, it’s interesting to see how they’re made. This factory machine takes rolls of plastic and uses a vacuum and heat to thermoform thousands of cups an hour. After it spits out cups, spinning brushes sort them into rows for stacking and packaging.

The Awesomer

Laravel DataMigrator Package

https://repository-images.githubusercontent.com/606438103/ca84c3ad-ec7a-4395-835b-4d4fcfa35d6e

Data Migrator

Latest Version on Packagist
GitHub Tests Action Status
GitHub Code Style Action Status
Total Downloads

Data Migrator is a PHP/Laravel package that helps you migrate data from one model to another, even if they have
different
structures.
It’s especially useful when you’re migrating data between models with different database schemas.

Installation

You can install the package via composer:

composer require oguzhankrcb/datamigrator

Usage

Transforming Data

To transform data from one model to another, use the transformData method. This method takes two arrays:
$toModelPrototype and $fromModel.

$toModelPrototype should be an array that describes the structure of the new model, with the keys being the names of
the
new fields, and the values being the names of the fields from the old model that the new fields should be based on. For
example:

$toModelPrototype = [
    'id'         => '[id]',
    'unique_id'  => '[unique_number.id]',
    'name'       => '[data->name]',
    'categories' => [
        'first_category'  => '[data->categories->category_2]',
        'second_category' => '[data->categories->category_3]',
    ],
    'alias_with_item_code' => '[data->alias][data->item->code]',
    'alias'                => '[data->alias]',
    'item_code'            => '[data->item->code]',
    'status'               => '[data->status]',
];

$fromModel should be an array that represents a single row of data from the old model, with the keys being the names
of the fields from the old model, and the values being the actual values.
For example:

$fromModel = [
    'id'            => 1,
    'unique_number' => 'lxAxmUlkfc',
    'data'          => [
        'name'       => 'John Doe',
        'alias'      => 'JD',
        'categories' => [
            'category_1' => 'Bronze',
            'category_2' => 'Silver',
            'category_3' => 'Gold',
        ],
        'item' => [
            'code' => 196854,
        ],
        'status' => true,
    ],
];

Here’s an example of how to use transformData:

use Oguzhankrcb\DataMigrator\Facades\DataMigrator;

$newData = DataMigrator::transformData($toModelPrototype, $fromModel);

The $newData array will contain the transformed data, with the keys being the names of the new fields, and the values
being the corresponding values from the old model.

Output Example:

[
    'id'         => 1,
    'unique_id'  => 'lxAxmUlkfc1',
    'name'       => 'John Doe',
    'categories' => [
        'first_category'  => 'Silver',
        'second_category' => 'Gold',
    ],
    'alias_with_item_code' => 'JD196854',
    'alias'                => 'JD',
    'item_code'            => '196854',
    'status'               => true,
]

Transferring Data

To transfer all data from one model to another, use the transferAllDataFromModelToModel method. This method takes
three
arguments: $transferToModel, $toModelPrototype, and $transferFromModel.

$transferToModel should be the fully qualified class name of the model you want to transfer the data to. For example:

$transferToModel = \App\Models\User::class;

$toModelPrototype should be the same array you used with transformData.

$transferFromModel should be the fully qualified class name of the model you want to transfer the data from. For
example:

$transferFromModel = \App\Models\LegacyUser::class;

Here’s an example of how to use transferAllDataFromModelToModel:

use App\Models\Order;
use App\Models\Invoice;
use Oguzhankrcb\DataMigrator\Facades\DataMigrator;

// Define the fields to transfer from Order to Invoice
$toModelPrototype = [
    'invoice_number' => '[order_number]',
    'customer_name' => '[customer->name]',
    'customer_email' => '[customer->email]',
    'total_amount' => '[amount]',
    'total_amount_with_currency' => '[amount]€',
];

// Transfer the data from Order to Invoice
DataMigrator::transferAllDataFromModelToModel(Invoice::class, $toModelPrototype, Order::class);

In this example, we define the fields we want to transfer from the Order model to the Invoice model using the
$toModelPrototype array. Then we call the
transferAllDataFromModelToModel method, passing in the Invoice and Order models and the $toModelPrototype array.

This method will transfer all the data from the Order model to the Invoice model, creating a new Invoice model for
each
Order model in the database.

If you want to transfer only one model data to another model you can use transferDataModelToModel method
only difference from the transferAllDataFromModelToModel method is this method only transfers one model not all
models.

Here’s an example of how to use transferDataModelToModel:

use App\Models\Order;
use App\Models\Invoice;
use Oguzhankrcb\DataMigrator\Facades\DataMigrator;

// Define the fields to transfer from Order to Invoice
$toModelPrototype = [
    'invoice_number' => '[order_number]',
    'customer_name' => '[customer->name]',
    'customer_email' => '[customer->email]',
    'total_amount' => '[amount]',
    'total_amount_with_currency' => '[amount]€',
];

$orderInstance = Order::find(1);

// Transfer the data from Order to Invoice
$transferedModel = DataMigrator::transferDataModelToModel(Invoice::class, $toModelPrototype, $orderInstance);

Testing

Changelog

Please see CHANGELOG for more information on what has changed recently.

Contributing

Contributions are welcome! If you find any bugs or issues,
please open a new issue or submit a pull request.

Security Vulnerabilities

Please review our security policy on how to report security vulnerabilities.

Credits

License

The DataMigrator package is open-source software licensed under the MIT license.

Laravel News Links

How to Use the tee Command to Split Terminal Output on Linux

https://static1.makeuseofimages.com/wordpress/wp-content/uploads/2023/03/tee-command-in-linux.jpg

Linux lets you store the command output in files as a means of output redirection. When you save the output to a file using the > or >> operators, the output gets redirected with no information displayed on the terminal.

But what if you want to print the output on the screen and store it in a file simultaneously? Although you can’t do it with the output redirection operators, it is possible to do so using the tee command on Linux.

Basic Command Syntax

tee is a standard Linux utility used to split the output of a command between the standard output and files.

Unlike most Linux commands, tee is used with other programs using a pipe (|). The pipe operator—one of the many command-line operators on Linux—lets a program use another command’s output as its input. You might have used pipe while using grep alongside the ls command or cat.

The basic syntax of the tee command is:

 command | tee options filepath 

…where options and filepath are the command-line arguments and the path to the file you want to store the output in.

Split Terminal Output on Linux With tee

The simplest use of tee is to split the output to display it in the terminal as well as store it inside a file. For instance, to store the output of the ls command to a text file named “output.txt,” run:

 ls | tee ./output.txt 

The output will display the contents of the present working directory as usual. On checking the output.txt file, you’ll find that tee saved the output to the file as well.

When you specify a file path, tee checks if the file exists. If it doesn’t find one, it automatically creates the file for you, making it convenient for use in shell scripts. It is useful when you want to log the output of a program or script for later reference.

You’ll have to preface the tee command with sudo to read or store data to a file owned by the root user.

If the specified file has data stored inside that you don’t want to overwrite, use the -a flag to append the output to the file, instead of clearing the entire file and then saving the data:

 ls | tee -a ./output.txt 

Similarly, you can redirect the output to multiple files by specifying the paths, separated by single spaces:

 ls | tee ./output1.txt ./output2.txt 

Sometimes, unexpected errors or manual interruptions (using Ctrl + C or Ctrl + Z) in the former command can cause tee to quit. To ignore such interruptions, use the -i flag:

 ls | tee -i output.txt 

To get command-line help regarding tee or find the version details, use the –help and –version flags as follows:

 tee --help
tee --version

Redirecting the Output to Another Command

You can create an output chain by piping tee with other Linux commands. Doing so will save the output to the specified file and then pass it on to the next command for processing.

Use the following format to redirect tee’s output to another command:

 command | tee filepath | othercommand 

For example, the following command will save the ls command output to output.txt before finally redirecting it to grep for a quick search:

 ls | tee output.txt | grep "Documents" 

Overall, you can use the tee command to play around with the standard input and output on Linux.

Manipulating Output and Text With Linux Commands

The tee command adds much-needed functionality to the standard output redirection operators on Linux. You can even use it to manipulate the output of a command before passing it on to another program.

Similarly, you can modify text using the terminal with the help of some standard Linux commands. They might take some time to get used to, but in the end, text manipulation via the command line is worth learning for any system administrator.

MakeUseOf

An Ergonomic Aid for Lifting Heavy Pots and Pans

https://s3files.core77.com/blog/images/1357381_81_120135_fnEvNlenZ.png

If you are young and able-bodied, you can take the form factor of the frying pan for granted. But if you’ve ever injured your wrist or simply have hit a certain age, lifting a heavy cast-iron pan loaded with food becomes a wildly unergonomic, even painful, task.

For this reason a company called Kitchinventions designed the Pan Buddy, a two-piece contraption made of heat-resistant nylon.

The first part slips over the handle of the pot or pan, loosely; the second part then screws down through the first part to make contact with the handle and hold everything fast. You can then lift the pan with a more ergonomic "handshake" alignment, easing the stress on your wrist. (As a bonus, it also obviates the need for additional heat protection from a cast-iron handle.)

I’d love it if the thing was more attractive, but it seems effective and is admittedly form follows function. They run $20 a pop.

Core77